diff --git a/D3Launch/3D_detect.cpp b/D3Launch/3D_detect.cpp new file mode 100644 index 00000000..76f6db1f --- /dev/null +++ b/D3Launch/3D_detect.cpp @@ -0,0 +1,510 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/3D_detect.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 15 5/19/99 12:29p Nate + * Fixed openGL crash, changed Network speed default, changed OpenGL + * detection to default to unchecked, and removed config file parsing from + * US version + * + * 14 3/11/99 10:54a Nate + * Changed "3Dfx Glide - Voodoo3" to only show up for Voodoo3 builds that + * don't include all APIs + * + * 13 3/09/99 11:57a Nate + * Changed "Voodoo Graphics Family" to "Voodoo3" for OEM_VOODOO3 builds + * + * 12 10/19/98 11:04a Nate + * More fixes to eliminate detection of software-only OpenGL + * + * 11 10/18/98 2:43p Nate + * Undid some of the suggested Glide init "fixes", as they would sometimes + * cause Direct3D enumeration to crash + * + * 10 10/16/98 3:18p Nate + * + * 9 10/15/98 7:30p Nate + * + * 8 10/13/98 3:03p Nate + * More fixes and changes. + * + * 7 10/12/98 7:13p Nate + * Fixed several bugs. + * + * 6 10/08/98 6:23p Nate + * Fixed a few bugs. + * + * 5 9/18/98 5:18p Nate + * Added a card type to the 3dfx Glide board detection type. + * + * 4 9/02/98 9:48a Nate + * Fixed hardware accelerator display bug in the Speed Tab + * + * 3 9/01/98 7:15p Nate + * Major Revision #2 + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +#define DYNAHEADER +#define DYNAHEADER_CREATE_STORAGE + +#include "stdafx.h" +#include "dyna_glide.h" +#include "module.h" + +#include "pserror.h" +#include "PsTypes.h" +#include "3d_detect.h" +#include "gl.h" + +#include "D3Launch.h" +#include "VideoTab.h" + +#undef D3D_OVERLOADS +#include "d3d.h" +#include "ddraw.h" + +card3d Cards[MAX_CARDS]; +int Num_cards = 0; + +#define MAX_D2D_DEVICES 8 +#define MAX_D3D_DEVICES 16 + +typedef struct d3d_device { + GUID guid_2d; + LPGUID pguid_2d; + + GUID guid_3d; + LPGUID pguid_3d; + + char name[1024]; +} d3d_device; + +d3d_device D2D_devices[MAX_D2D_DEVICES]; +d3d_device D3D_devices[MAX_D3D_DEVICES]; + +int Num_d2d_devices = 0; +int Num_d3d_devices = 0; + +// The enumeration callback for D3D devices +HRESULT WINAPI gr_d3d_enum( LPGUID lpGUID, + LPSTR lpDeviceDescription, + LPSTR lpDeviceName, + LPD3DDEVICEDESC lpHWDesc, + LPD3DDEVICEDESC lpHELDesc, + LPVOID lpContext ) +{ + int use_it = 0; + +// mprintf(( "Found 3d device %s: %s\n", lpDeviceName, lpDeviceDescription )); + + if ( lpHWDesc && lpHWDesc->dwFlags != 0 ) { + use_it = 1; + } //else if ( lpHELDesc ) { + + + if ( use_it ) { + d3d_device *d2d = (d3d_device *)lpContext; + d3d_device *d3d = (d3d_device *)&D3D_devices[Num_d3d_devices++]; + + if ( lpGUID ) { + memmove( &d3d->guid_3d, lpGUID, sizeof(GUID) ); + d3d->pguid_3d = &d3d->guid_3d; + } else { + memset( &d3d->guid_3d, 0, sizeof(GUID) ); + d3d->pguid_3d = NULL; + } + + memmove( &d3d->guid_2d, &d2d->guid_2d, sizeof(GUID) ); + if ( d2d->pguid_2d ) { + d3d->pguid_2d = &d3d->guid_2d; + } else { + d3d->pguid_2d = NULL; + } + + //strcpy( d3d->name, "Direct 3D - " ); + strcpy( d3d->name, d2d->name ); + } + + return D3DENUMRET_OK; +} + +// The enumeration callback for 2D +BOOL WINAPI gr_d2d_enum( LPGUID lpGUID, + LPSTR lpDeviceDescription, + LPSTR lpDeviceName, + LPVOID lpContext ) +{ + + d3d_device *d2d = (d3d_device *)&D2D_devices[Num_d2d_devices++]; + +// mprintf(( "Found 2d device %s: %s\n", lpDeviceName, lpDeviceDescription )); + + if ( lpGUID ) { + memmove( &d2d->guid_2d, lpGUID, sizeof(GUID) ); + d2d->pguid_2d = &d2d->guid_2d; + } else { + memset( &d2d->guid_2d, 0, sizeof(GUID) ); + d2d->pguid_2d = NULL; + } + + strcpy( d2d->name, lpDeviceDescription ); +// strcat( d2d->name, lpDeviceName ); + + return D3DENUMRET_OK; +} + +HRESULT (__stdcall *pfn_DirectDrawEnumerate) (LPDDENUMCALLBACK, LPVOID) = NULL; +HRESULT (__stdcall *pfn_DirectDrawCreate) (GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR *) = NULL; + +// Check for any Direct 3D devices +void check_direct3d() +{ + int i; + HRESULT ddrval; + LPDIRECTDRAW lpDD1=NULL; + LPDIRECT3D2 lpD3D=NULL; + + Num_d2d_devices = 0; + Num_d3d_devices = 0; + + if (!Dd_dll_handle) + return; + + if (!pfn_DirectDrawCreate) + pfn_DirectDrawCreate = (HRESULT (__stdcall *) (GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR *)) GetProcAddress(Dd_dll_handle, "DirectDrawCreate"); + if (!pfn_DirectDrawCreate) + goto D3DError; + + if (!pfn_DirectDrawEnumerate) + pfn_DirectDrawEnumerate = (HRESULT (__stdcall *) (LPDDENUMCALLBACK, LPVOID)) GetProcAddress(Dd_dll_handle, "DirectDrawEnumerateA"); + if (!pfn_DirectDrawEnumerate) + goto D3DError; + + ddrval = pfn_DirectDrawEnumerate( gr_d2d_enum, NULL ); + if ( ddrval != DD_OK ) { + OutputDebugString( "GR_D3D_INIT: DirectDrawEnumerate failed.\n" ); + goto D3DError; + } + + for ( i=0; ipguid_2d, &lpDD1, NULL ); + if ( ddrval != DD_OK ) { + OutputDebugString( "GR_D3D_INIT: DirectDrawCreate failed.\n" ); + goto D3DError; + } + + ddrval = lpDD1->QueryInterface( IID_IDirect3D2, ( LPVOID *) &lpD3D ); + if ( ddrval != DD_OK ) { + OutputDebugString( "GR_D3D_INIT: QueryInterface failed.\n" ); + goto D3DError; + } + + ddrval = lpD3D->EnumDevices(gr_d3d_enum, d2d ); + if ( ddrval != DD_OK ) { + OutputDebugString( "WIN_DD32: D3D enum devices failed. (0x%x)\n");//, ddrval ); + } + + lpD3D->Release(); + lpD3D = NULL; + + lpDD1->Release(); + lpDD1 = NULL; + } + + // Store Direct3D devices in number of cards + for ( i=0; iRelease(); + lpD3D = NULL; + } + + if(lpDD1!=NULL) { + lpDD1->Release(); + lpDD1 = NULL; + } + //mprintf(( "Direct3D Polling failed.\n" )); + + return; +} + +void check_glide() +{ + static GrHwConfiguration hwconfig; + module *GlideDLLHandle; + + if ( !(GlideDLLHandle=LoadGlideDLL()) ) { + //mprintf(( "Glide DLL not found!\n" )); + return; + } + + if (!GlideInited) { + + // Check if any 3dfx systems are present + grSstQueryBoards(&hwconfig); + if(hwconfig.num_sst<=0) { + mod_FreeModule(GlideDLLHandle); + return; + } + + grGlideInit(); + GlideInited=TRUE; + + if (grSstQueryHardware(&hwconfig)==0 || hwconfig.num_sst<1) + { + // Glide is now only shutdown when the application exits + //grGlideShutdown(); + mod_FreeModule(GlideDLLHandle); + return; + } + + grGlideShutdown(); + } + + if(hwconfig.num_sst<=0) { + mod_FreeModule(GlideDLLHandle); + return; + } + + Cards[Num_cards].renderer_type=RENDERER_GLIDE; + + switch(hwconfig.SSTs[0].type) { + case GR_SSTTYPE_VOODOO: +#if (defined(OEM_VOODOO3) && !defined(USE_ALL_VIDEO_OPTIONS)) + strcpy( Cards[Num_cards].name, "Voodoo3" ); +#else + strcpy( Cards[Num_cards].name, "Voodoo Graphics Family" ); +#endif + break; + case GR_SSTTYPE_SST96: + strcpy( Cards[Num_cards].name, "SST96" ); + break; + case GR_SSTTYPE_AT3D: + strcpy( Cards[Num_cards].name, "AT3D" ); + break; + default: + strcpy( Cards[Num_cards].name, "" ); + break; + } + Num_cards++; + + // Glide is now only shutdown when the application exits + //grGlideShutdown(); + + mod_FreeModule(GlideDLLHandle); +} + +// Shuts down glide (if it has been initialized) +void shutdown_glide(void) +{ + if(GlideInited) { + module *GlideDLLHandle; + + if ( (GlideDLLHandle=LoadGlideDLL()) ) { + grGlideShutdown(); + mod_FreeModule(GlideDLLHandle); + } + } +} + +// OpenGL function pointer type definitions +typedef const GLubyte *(CALLBACK* LPFN_GLGETSTRING)(GLenum); +typedef BOOL (CALLBACK *LPFN_WGLMAKECURRENT)(HDC, HGLRC); +typedef HGLRC (CALLBACK *LPFN_WGLCREATECONTEXT)(HDC); +typedef BOOL (CALLBACK *LPFN_WGLDELETECONTEXT)(HGLRC); + +// Check for OpenGL support, and add it to list +void check_openGL() +{ + LPFN_GLGETSTRING pfn_glGetString=NULL; + LPFN_WGLMAKECURRENT pfn_wglMakeCurrent=NULL; + LPFN_WGLCREATECONTEXT pfn_wglCreateContext=NULL; + LPFN_WGLDELETECONTEXT pfn_wglDeleteContext=NULL; + + // Check for the OpenGL dll, and open it + if(opengl_dll_handle==NULL) { + opengl_dll_handle=LoadLibrary("opengl32.dll"); + if(opengl_dll_handle==NULL) { + OutputDebugString("OpenGL DLL not found.\n"); + return; + } + } + + // Get the functions to check the OpenGL renderer + pfn_glGetString = (LPFN_GLGETSTRING)GetProcAddress(opengl_dll_handle,"glGetString"); + pfn_wglCreateContext = (LPFN_WGLCREATECONTEXT)GetProcAddress(opengl_dll_handle,"wglCreateContext"); + pfn_wglDeleteContext = (LPFN_WGLDELETECONTEXT)GetProcAddress(opengl_dll_handle,"wglDeleteContext"); + pfn_wglMakeCurrent = (LPFN_WGLMAKECURRENT)GetProcAddress(opengl_dll_handle,"wglMakeCurrent"); + if (!pfn_glGetString || !pfn_wglCreateContext || + !pfn_wglDeleteContext || !pfn_wglMakeCurrent) { + OutputDebugString("Could not obtain pfn_glGetString().\n"); + return; + } + + // Make sure the video tab has been initialized first + if(CurrentVideoTab==NULL) { + OutputDebugString("The Video Tab was not set.\n"); + return; + } + + // Get the window device context + // NOTE:the window is now set to the scanning window that is + // displayed just before detect_3dcards() is called, and + // destroyed afterwords - this function will fail if + // it is called in any other context. + HDC hOpenGLDC = GetDC(CurrentVideoTab->m_MsgDlg.m_hWnd); + if(hOpenGLDC==NULL) { + OutputDebugString("GetDC() failed.\n"); + return; + } + + // Finds an acceptable pixel format to render to + PIXELFORMATDESCRIPTOR pfd, pfd_copy; + int pf; + + memset(&pfd, 0, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_GENERIC_ACCELERATED; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 16; + pfd.cDepthBits =16; + + // Find the user's "best match" PFD + pf = ChoosePixelFormat(hOpenGLDC, &pfd); + if (pf == 0) + { + OutputDebugString("ChoosePixelFormat() failed.\n"); + return; + } + + // Try and set the new PFD + if (SetPixelFormat(hOpenGLDC, pf, &pfd) == FALSE) + { + DWORD ret=GetLastError(); + OutputDebugString("SetPixelFormat() failed.\n"); + return; + } + + // Get a copy of the newly set PFD + if(DescribePixelFormat(hOpenGLDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd_copy)==0) + { + OutputDebugString("DescribePixelFormat() failed.\n"); + return; + } + + // Check the returned PFD to see if it is hardware accelerated + if((pfd_copy.dwFlags & PFD_GENERIC_ACCELERATED)==0 && (pfd_copy.dwFlags & PFD_GENERIC_FORMAT)!=0) { + OutputDebugString("Returned OpenGL device is not hardware accelerated.\n"); + return; + } + + // Create an OpenGL context, and make it the current context + HGLRC ResourceContext; + ResourceContext = pfn_wglCreateContext((HDC)hOpenGLDC); + if(ResourceContext==NULL) { + DWORD ret=GetLastError(); + OutputDebugString("wglCreateContext() failed.\n"); + return; + } + pfn_wglMakeCurrent((HDC)hOpenGLDC, ResourceContext); + + // Add the OpenGL type to card list + Cards[Num_cards].renderer_type=RENDERER_OPENGL; + sprintf(Cards[Num_cards].name,"%s",pfn_glGetString(GL_RENDERER)); + Num_cards++; + + // Clean up + pfn_wglMakeCurrent(NULL, NULL); + pfn_wglDeleteContext(ResourceContext); + ReleaseDC(CurrentVideoTab->m_hWnd,hOpenGLDC); +} + + +// Fills in Cards and Num_cards +void detect_3dcards(int detect_direct3d, int detect_glide, int detect_opengl) +{ + if(VideoCardsDetected) return; + + Num_cards = 0; + + //CString no_3d_msg; + //no_3d_msg.LoadString(IDS_3D_DETECT_NO3D); + //strcpy( Cards[Num_cards++].name, no_3d_msg ); + + // Put in the "none" option + Cards[Num_cards].renderer_type=RENDERER_NONE; + strcpy(Cards[Num_cards].name,""); + Num_cards++; + + // Check for the other types + if(detect_opengl) check_openGL(); + if(detect_glide) check_glide(); + if(detect_direct3d) check_direct3d(); + + //VideoCardsDetected=TRUE; +} + +// Creates a string suitable for the list box +// (combines the renderer_type and the device name) +char *GetFullName(card3d *card) +{ + static char name[1024]; + CString temp; + + // empty out the name + strcpy(name,""); + + // Copy the renderer type in + switch(card->renderer_type) { + case RENDERER_SOFTWARE_8BIT: + strcpy(name,"Software (8 bit)"); + break; + case RENDERER_SOFTWARE_16BIT: + strcpy(name,"Software (16 bit)"); + break; + case RENDERER_OPENGL: + strcpy(name,"OpenGL"); + break; + case RENDERER_DIRECT3D: + strcpy(name,"Direct3D"); + break; + case RENDERER_GLIDE: + strcpy(name,"3Dfx Glide"); + break; + default: + temp.LoadString(IDS_3D_DETECT_NO3D); + strcpy(name,temp.GetBuffer(0)); + break; + } + + // tack on the Device name (if there is one) + if(strlen(card->name)>0) { + strcat(name," - "); + strcat(name,card->name); + } + + return(name); +} diff --git a/D3Launch/3D_detect.h b/D3Launch/3D_detect.h new file mode 100644 index 00000000..a9997524 --- /dev/null +++ b/D3Launch/3D_detect.h @@ -0,0 +1,69 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/3D_detect.h $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * Code to detect what 3d cards you have + * + * $Log: not supported by cvs2svn $ + * + * 6 10/15/98 7:30p Nate + * + * 5 10/12/98 7:13p Nate + * Fixed several bugs. + * + * 4 9/01/98 7:15p Nate + * Major Revision #2 + * + * 3 8/05/98 11:54a Nate + * Initial Version + * + * 2 7/27/98 11:46a Nate + * Added D3Launch + * + * 1 7/27/98 11:45a Nate + * + * 2 3/07/98 2:55p John + * Added tabs for different devices in setup + * + * 1 2/18/98 4:07p John + * + * $NoKeywords: $ + */ + + +#ifndef _3D_DETECT_H +#define _3D_DETECT_H + +#include "PsTypes.h" + +#define MAX_CARDS 16 + +// The list of rendering device types +typedef enum +{ + RENDERER_SOFTWARE_8BIT, + RENDERER_SOFTWARE_16BIT, + RENDERER_OPENGL, + RENDERER_DIRECT3D, + RENDERER_GLIDE, + RENDERER_NONE +} RendererType; + +// The structure for a 3D device +typedef struct card3d { + char name[1024]; + RendererType renderer_type; +} card3d; + +extern card3d Cards[MAX_CARDS]; +extern int Num_cards; + +// Fills in Cards and Num_cards +// If really_detect is 0, just find the software only one. +void detect_3dcards(int detect_direct3d, int detect_glide, int detect_opengl); +char *GetFullName(card3d *card); +void shutdown_glide(void); + +#endif //_3D_DETECT_H diff --git a/D3Launch/AudioTab.cpp b/D3Launch/AudioTab.cpp new file mode 100644 index 00000000..545a54b1 --- /dev/null +++ b/D3Launch/AudioTab.cpp @@ -0,0 +1,1018 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/AudioTab.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 39 9/29/99 10:39a Nate + * Aureal OEM now allows other mixers + * + * 38 8/19/99 6:13p Samir + * detect vortex1 chipsets. + * + * 37 6/09/99 2:46p Nate + * Minor changes for different builds + * + * 35 5/20/99 1:08p Samir + * fixed EAX check. + * + * 34 5/20/99 12:53p Nate + * Added GLSetup window, EAX mixer support, and CHFlight+Mouseman Mode + * options + * + * 33 4/27/99 10:41p Nate + * Added 16bit dsound support + * + * 32 3/29/99 4:34p Samir + * better checking of results from Aureal initialization. + * + * 31 3/29/99 4:25p Nate + * changed aureal check. + * + * 30 3/29/99 4:08p Samir + * check for Aureal 2.0 reflections to see if hardware is supported. + * + * 29 3/29/99 3:52p Samir + * Check for occlusions feature in Aureal after initialized. + * + * 28 3/29/99 3:21p Samir + * added aureal 2.0 check. + * + * 27 3/29/99 3:14p Nate + * Added OEM_GENERIC + * + * 26 3/04/99 12:07p Nate + * Made Software the default mixer (if it's available) + * + * 25 2/28/99 5:31p Nate + * Disabled DS3D and Aureal mixers for the Voodoo3 OEM + * + * 24 2/05/99 3:51p Nate + * Added conditional compilation directives for OEM support + * + * 23 10/23/98 6:48p Nate + * more fixes. + * + * 22 10/23/98 5:29p Nate + * Small fixes. + * + * 21 10/21/98 4:51p Nate + * More fixes. + * + * 20 10/18/98 2:43p Nate + * Dimmed D3D and Aureal Mixer options for the demo + * + * 19 10/15/98 10:54a Nate + * Added Launcher Sound toggling + * + * 18 10/14/98 5:52p Nate + * More fixes + * + * 17 10/14/98 11:37a Nate + * Added default to DS8 for Chris + * + * 16 10/13/98 3:03p Nate + * More fixes and changes. + * + * 15 10/12/98 8:16p Nate + * Commented out "old Aureal DLL" messages for now + * + * 14 10/12/98 7:13p Nate + * Fixed several bugs. + * + * 13 10/10/98 4:05p Nate + * Added detection/scanning window messages + * + * 12 10/10/98 2:33p Nate + * More fixes. + * + * 11 10/08/98 6:23p Nate + * Fixed a few bugs. + * + * 10 9/25/98 6:57p Nate + * If no card is in registry, the list box now defaults to none. + * + * 9 9/22/98 3:33p Nate + * Added conditional compiling to help system (can toggle between HTML and + * standard windows help) + * + * 8 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 7 9/21/98 12:12p Nate + * Changed "Soundcard" registry value name to "SoundcardName" + * + * 6 9/01/98 7:15p Nate + * Major Revision #2 + * + * 5 8/31/98 6:44p Nate + * Major Revision + * + * 4 8/10/98 10:44a Nate + * Added Language selection support + * + * 3 8/05/98 4:52p Nate + * Added registry reading and writing. + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +// AudioTab.cpp : implementation file +// + +#include "stdafx.h" +#include "afxpriv.h" +#include "afxext.h" +#include "D3Launch.h" +#include "D3LaunchDlg.h" +#include "AudioTab.h" + +#include +#include +#include +#include +#include + +#include "ia3dapi.h" +#include "ia3dutil.h" +#include "eax.h" + +//#include "VerifyA3D.h" +#include "OS_Config.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define MAX_CARDS 32 + +#define SBT_PRIMARY 0 + +// Supported sound mixers (for saving to registry) +#define SOUND_MIXER_SOFTWARE_16 0 +#define SOUND_MIXER_DS_16 1 +#define SOUND_MIXER_DS_8 2 +#define SOUND_MIXER_DS3D_16 3 +#define SOUND_MIXER_AUREAL_16 4 +#define SOUND_MIXER_NONE 5 +#define SOUND_MIXER_EAX 6 + +// Setup available mixer flags +#define SOFTWARE_MIXER 0x01 +#define DS8BIT_MIXER 0x02 +#define DS16BIT_MIXER 0x04 +#define DS3D_MIXER 0x08 +#define AUREAL_MIXER 0x10 +#define EAX_MIXER 0x20 + +typedef struct { + GUID guid; + LPGUID pguid; + + char name[1024]; // Name of the device + UINT mixers; // Mixers supported by device +} SoundCard; + +static SoundCard Cards[MAX_CARDS]; +static int Num_cards; + +// the callback for the DirectSound enumeration process +BOOL WINAPI dsound_enum_callback +( + GUID FAR * lpGuid, + LPSTR lpDeviceDescription, + LPSTR lpDeviceName, + LPVOID lpContext +) +{ + SoundCard *card=&Cards[Num_cards++]; + + if ( lpGuid ) { + memmove( &card->guid, lpGuid, sizeof(GUID) ); + card->pguid = &card->guid; + } else { + memset( &card->guid, 0, sizeof(GUID) ); + card->pguid = NULL; + } + + // Save name of device + sprintf(card->name, "%s", lpDeviceDescription); + + return TRUE; +} + + +// Creates a Primary direct sound buffer +HRESULT +CreateDSBuffer +( + LPDIRECTSOUND lpDirectSound, + int buffer_type, + LPDIRECTSOUNDBUFFER *lp_lp_dsb, + DWORD sound_bytes, + DWORD frequency, + bool f_is_stereo, + bool f_is_16_bit, + bool positional +) +{ + DSBUFFERDESC dsbd; + tWAVEFORMATEX fmt; + HRESULT result; + + if(frequency != 44100 && frequency != 22050 && frequency != 11025) + return 0; + + if(lpDirectSound==NULL) + return 0; + + // Setup the wave format + fmt.nChannels = (f_is_stereo)?2:1; + fmt.wBitsPerSample = (f_is_16_bit)?16:8; + fmt.nSamplesPerSec = ((DWORD)frequency); + fmt.nBlockAlign = fmt.nChannels*(fmt.wBitsPerSample>>3); + fmt.nAvgBytesPerSec = ((DWORD)fmt.nSamplesPerSec)*((DWORD)fmt.nBlockAlign); + fmt.wFormatTag = WAVE_FORMAT_PCM; + + // Setup the secondary direct sound buffer + memset(&dsbd, 0, sizeof(dsbd)); + dsbd.lpwfxFormat = (LPWAVEFORMATEX)&fmt; + dsbd.dwSize = sizeof(DSBUFFERDESC); + dsbd.dwBufferBytes = sound_bytes; + + // Setup for Software 16 bit mixer + dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2; + + if(buffer_type != SBT_PRIMARY) return 0; + + //m_primary_frequency = m_current_frequency = frequency; + //m_primary_bit_depth = fmt.wBitsPerSample; + //m_primary_alignment = fmt.nBlockAlign; + + dsbd.lpwfxFormat = NULL; + dsbd.dwBufferBytes = 0; + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2; + if (positional) { + dsbd.dwFlags |= DSBCAPS_CTRL3D; + } + + // Create the buffer + result = lpDirectSound->CreateSoundBuffer(&dsbd, lp_lp_dsb, 0); + + if (result == DS_OK && buffer_type == SBT_PRIMARY) + { + // Succeeded. Set primary buffer to desired format. + result = (*lp_lp_dsb)->SetFormat(&fmt); + } + + return result; +} + + +BOOL Aureal2Check(LPGUID lpguid) +{ + BOOL retval=FALSE; + IA3d4 *lpAureal3d; + HRESULT hr; + + hr = A3dInitialize(); + if (SUCCEEDED(hr)) { + hr = A3dCreate(lpguid, (void **)&lpAureal3d, NULL, A3D_1ST_REFLECTIONS|A3D_OCCLUSIONS|A3D_DISABLE_SPLASHSCREEN); + if (hr == S_OK) { + // Successful Creation and initialization of a DirectSound Object + A3DCAPS_HARDWARE hwcaps; + memset(&hwcaps, 0 , sizeof(hwcaps)); + hwcaps.dwSize = sizeof(hwcaps); + hr = lpAureal3d->GetHardwareCaps(&hwcaps); + if (hr == S_OK) { + if (hwcaps.dwFlags & A3D_DIRECT_PATH_A3D) { + if (lpAureal3d->IsFeatureAvailable(A3D_OCCLUSIONS) == TRUE) { + retval = TRUE; + } + } + } + + // Old driver/DLL + //CString a3d_msg, title_msg; + //title_msg.LoadString(IDS_AUDIOTAB_WARNING); + //a3d_msg.LoadString(IDS_AUDIOTAB_A3D1); + //MessageBox(NULL, a3d_msg, title_msg, MB_OK | MB_ICONEXCLAMATION ); + lpAureal3d->Release(); + } + A3dUninitialize(); + } + return retval; +} + + +BOOL CreativeEAXCheck(LPDIRECTSOUND lpds) +{ + BOOL retval=FALSE; + DWORD properties=0; + ULONG ulAnswer=0; + LPKSPROPERTYSET lpksps = NULL; + WAVEFORMATEX wave; + DSBUFFERDESC dsbdesc; + LPDIRECTSOUNDBUFFER lpdsb=NULL; + + const DWORD EAX_ENVIRONMENTS_AVAILABLE = 1, + EAX_BUFFERMIX_AVAILABLE =2; + + memset(&wave, 0, sizeof(WAVEFORMATEX)); + wave.wFormatTag = WAVE_FORMAT_PCM; + wave.nChannels = 1; + wave.nSamplesPerSec = 11025; + wave.wBitsPerSample = 8; + wave.nBlockAlign = wave.wBitsPerSample / 8 * wave.nChannels; + wave.nAvgBytesPerSec = wave.nSamplesPerSec * wave.nBlockAlign; + + memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_STATIC|DSBCAPS_CTRL3D; + dsbdesc.dwBufferBytes = DSBSIZE_MIN*2; + dsbdesc.lpwfxFormat = &wave; + + if ( FAILED(lpds->CreateSoundBuffer(&dsbdesc, &lpdsb, NULL)) ) { + retval = FALSE; + } + else if ( FAILED(lpdsb->QueryInterface(IID_IKsPropertySet, (LPVOID *)&lpksps)) ) { + retval = FALSE; + } + else if (FAILED(lpksps->QuerySupport(DSPROPSETID_EAX_ReverbProperties, DSPROPERTY_EAX_ALL, &ulAnswer)) ) { + retval = FALSE; + } + else { + if ( (ulAnswer & KSPROPERTY_SUPPORT_SET|KSPROPERTY_SUPPORT_GET) == (KSPROPERTY_SUPPORT_SET|KSPROPERTY_SUPPORT_GET) ) { + properties |= EAX_ENVIRONMENTS_AVAILABLE; + if (FAILED(lpksps->QuerySupport(DSPROPSETID_EAXBUFFER_ReverbProperties, DSPROPERTY_EAXBUFFER_REVERBMIX, &ulAnswer)) ) { + retval = FALSE; + } + else { + properties |= EAX_BUFFERMIX_AVAILABLE; + } + } + else { + retval = FALSE; + } + } + + if (lpksps) { + lpksps->Release(); + } + if (lpdsb) { + lpdsb->Release(); + } + + if (properties & (EAX_BUFFERMIX_AVAILABLE+EAX_ENVIRONMENTS_AVAILABLE)) { + retval = TRUE; + } + + return retval; +} + + + +// Checks capabilities of given directsound device to see which mixers +// it can handle +bool DetermineMixerOptions(LPDIRECTSOUND lpDirectSound, UINT &mixer_flags) +{ + DSCAPS dscaps; + HRESULT hr; + + // Default to just having DirectSound 8 bit available + mixer_flags=DS8BIT_MIXER; + + dscaps.dwSize = sizeof(DSCAPS); + hr = lpDirectSound->GetCaps(&dscaps); + if(hr != DS_OK) { + return FALSE; + } + +/* We have decided to remove Direct Sound mixers as an option + // Check DirectSound 8 Bit support + if(dscaps.dwFlags & DSCAPS_PRIMARY8BIT) + mixer_flags |= DS8BIT_MIXER; + else + mixer_flags &= ~DS8BIT_MIXER; +*/ + // Check DirectSound 16 Bit support + if(dscaps.dwFlags & DSCAPS_PRIMARY16BIT) + mixer_flags |= DS16BIT_MIXER; + else + mixer_flags &= ~DS16BIT_MIXER; + +#if (!defined(DEMO) && !defined(OEM_VOODOO3)) + // Check DirectSound 3D Bit support + if(dscaps.dwMaxHw3DAllBuffers>0) + mixer_flags |= DS3D_MIXER; + else + mixer_flags &= ~DS3D_MIXER; +#endif + + // Check for Software and Creative EAX support + ////////////////////////////////////////////// + if(dscaps.dwFlags & DSCAPS_EMULDRIVER) + return TRUE; // In NT or bad sound card, so don't set software flag + + //Set the Cooperative level AND make sure it is ok to do it + HRESULT scl_status; + scl_status = lpDirectSound->SetCooperativeLevel(pLaunchDlg->m_hWnd, DSSCL_WRITEPRIMARY); + if(scl_status != DS_OK) + return TRUE; // don't set software flag + + // EAX support + if (CreativeEAXCheck(lpDirectSound)) { + mixer_flags |= EAX_MIXER; + } + + // Try and create a buffer + HRESULT result; + LPDIRECTSOUNDBUFFER lp_primary_buffer; + lp_primary_buffer=NULL; + + // test software + result=CreateDSBuffer(lpDirectSound, SBT_PRIMARY, &lp_primary_buffer, 0, 22050, true, true, false); + + // Make sure buffer was created successfully + if(lp_primary_buffer == NULL) + return TRUE; + + if(result!=DS_OK) { + lp_primary_buffer->Release(); + return TRUE; + } + + // Determine if we are running NT or have a bad Win95 sound card + { + DSBCAPS dsbcaps; + dsbcaps.dwSize = sizeof(DSBCAPS); + lp_primary_buffer->GetCaps(&dsbcaps); + + // Is you want to see the caps, here is where -- mprintf all you want + if(!(dsbcaps.dwFlags & DSBCAPS_LOCHARDWARE)) + { + lp_primary_buffer->Release(); + return TRUE; + } + } + + // Release the buffer + lp_primary_buffer->Release(); + + // Device passed all four software tests, so set the flag + mixer_flags |= SOFTWARE_MIXER; + + return TRUE; +} + +typedef BOOL (CALLBACK *LPFN_DIRECTSOUNDENUMERATE)(LPDSENUMCALLBACKA lpDSEnumCallback, LPVOID lpContext); +typedef HRESULT (CALLBACK *LPFN_DIRECTSOUNDCREATE)(GUID FAR * lpGuid,LPDIRECTSOUND * ppDS,IUnknown FAR * pUnkOuter); + +// Adds any Direct Sound devices to the list of available sound settings +void check_direct_sound() +{ + int j; + HINSTANCE ds_dll_handle; + HRESULT dsrval; + LPFN_DIRECTSOUNDENUMERATE pfn_DirectSoundEnumerate; + LPFN_DIRECTSOUNDCREATE pfn_DirectSoundCreate; + LPDIRECTSOUND lpDirectSound; + + ds_dll_handle = LoadLibrary("dsound.dll"); + if (ds_dll_handle==NULL) + return; + + // Get function pointers from DLL + pfn_DirectSoundEnumerate = (LPFN_DIRECTSOUNDENUMERATE) GetProcAddress(ds_dll_handle, "DirectSoundEnumerateA"); + if (pfn_DirectSoundEnumerate==NULL) { + OutputDebugString( "Could not find DirectSoundEnumerate()\n" ); + goto DSoundCleanup; + } + + pfn_DirectSoundCreate = (LPFN_DIRECTSOUNDCREATE) GetProcAddress(ds_dll_handle, "DirectSoundCreate"); + if (pfn_DirectSoundCreate==NULL) { + OutputDebugString( "Could not find DirectSoundCreate()\n" ); + goto DSoundCleanup; + } + + // Enumerate sound cards/devices on user's system + dsrval = pfn_DirectSoundEnumerate((LPDSENUMCALLBACKA)dsound_enum_callback, NULL ); + if ( dsrval != DS_OK ) { + OutputDebugString( "DirectSoundEnumerate failed.\n" ); + goto DSoundCleanup; + } + + // Evaluate mixer capabilities for each device + for(j=1; jlpVtbl->SetCooperativeLevel(lpDirectSound, hwnd, DSSCL_NORMAL); + // . + // . Place code to access DirectSound object here. + // . + DetermineMixerOptions(lpDirectSound,Cards[j].mixers); + lpDirectSound->Release(); + } + else { + OutputDebugString( "DirectSoundCreate failed.\n" ); + //goto DSoundCleanup; + } + +#if (!defined(DEMO) && !defined(OEM_VOODOO3)) + // Try to initialize Aureal 3D sound + { + if (Aureal2Check(Cards[j].pguid) == TRUE) { + Cards[j].mixers |= AUREAL_MIXER; + } + else { + Cards[j].mixers &= ~AUREAL_MIXER; + } + } +#endif + } + +DSoundCleanup: + FreeLibrary(ds_dll_handle); + return; +} + +///////////////////////////////////////////////////////////////////////////// +// CAudioTab property page + +IMPLEMENT_DYNCREATE(CAudioTab, CPropertyPage) + +CAudioTab::CAudioTab() : CPropertyPage(CAudioTab::IDD) +{ + //{{AFX_DATA_INIT(CAudioTab) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +CAudioTab::~CAudioTab() +{ +} + +// return 1 if there is Aureal support, otherwise return 0 +/* +int aureal_enabled() +{ + HRESULT hr; + HINSTANCE hinstance; + LPDIRECTSOUND pDS = NULL; // pointer to direct sound interface + LPIA3D2 pIA3d2 = NULL; + + + int aureal_enabled = 1; + + CoInitialize(NULL); + + hinstance = LoadLibrary( "dsound.dll" ); + if ( hinstance == NULL ) { + aureal_enabled = 0; + } + FreeLibrary(hinstance); + + // ensure a3d.dll exists + if ( aureal_enabled ) { + HINSTANCE a3d_handle; + a3d_handle = LoadLibrary("a3d.dll"); + if ( !a3d_handle ) { + aureal_enabled = 0; + } else { + FreeLibrary(a3d_handle); + } + } + + if ( aureal_enabled ) { + aureal_enabled = 0; + if ( SUCCEEDED(CoCreateInstance(CLSID_A3d, NULL, CLSCTX_INPROC_SERVER, IID_IDirectSound, (void**)&pDS ))) { + if ( SUCCEEDED(pDS->QueryInterface(IID_IA3d2, (void**)&pIA3d2)) ) { + A3DCAPS_SOFTWARE swCaps; + + /* Get Dll Software CAP to get DLL version number */ +/* ZeroMemory(&swCaps,sizeof(swCaps)); + + swCaps.dwSize = sizeof(swCaps); + pIA3d2->GetSoftwareCaps(&swCaps); +*/ + /* Compare version from a3d.dll to header version */ + /* only return A3D_OK if dll version >= to header version */ +/* + if (swCaps.dwVersion < A3D_CURRENT_VERSION) { + CString a3d_msg; + a3d_msg.LoadString(IDS_AUDIOTAB_A3D1); + MessageBox(NULL, a3d_msg, NULL, MB_OK | MB_ICONEXCLAMATION ); + } else { + + int aureal_verified; + aureal_verified = VerifyAurealA3D(); + + if (aureal_verified == FALSE) { + // This is fake A3D!!! Ignore + CString a3d_msg; + a3d_msg.LoadString(IDS_AUDIOTAB_A3D2); + MessageBox(NULL, a3d_msg, NULL, MB_OK | MB_ICONEXCLAMATION ); + } else { + if ( SUCCEEDED((hr = pDS->Initialize(NULL))) ) { + aureal_enabled = 1; + } + } + } + } + } + } + + if ( pDS != NULL ) { + pDS->Release(); + pDS = NULL; + } + + if ( pIA3d2 ) { + pIA3d2->Release(); + pIA3d2 = NULL; + } + + CoUninitialize(); + + return aureal_enabled; +} +*/ + +// Fills in Cards and Num_cards +void detect_sound_cards(int really_detect) +{ + Num_cards = 0; + + CString no_sound_msg; + no_sound_msg.LoadString(IDS_AUDIOTAB_NO_SOUND); + + // Setup "None" card slot + strcpy(Cards[Num_cards].name, no_sound_msg); + Cards[Num_cards].mixers=0; + Cards[Num_cards].pguid=NULL; + memset( &Cards[Num_cards].guid, 0, sizeof(GUID) ); + Num_cards++; + + if (really_detect) { + check_direct_sound(); + } +} + +void CAudioTab::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAudioTab) + DDX_Control(pDX, IDC_LAUNCHER_SND_CHECK, m_LauncherSndCheck); + DDX_Control(pDX, IDC_AUDIO_LIST, m_audio_list); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CAudioTab, CPropertyPage) + //{{AFX_MSG_MAP(CAudioTab) + ON_BN_CLICKED(IDC_BTN_AUDIO_DETECT, OnBtnAudioDetect) + ON_CBN_SELCHANGE(IDC_AUDIO_LIST, OnSelchangeAudioList) + ON_WM_HELPINFO() + ON_MESSAGE(WM_COMMANDHELP,OnCommandHelp) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CAudioTab message handlers + +void CAudioTab::OnBtnAudioDetect() +{ + // TODO: Add your control notification handler code here + int i; + + // Set the wait cursor + CWaitCursor wc; + + // Display the scanning window + m_MsgDlg.m_ScanningMsg.LoadString(IDS_AUDIOTAB_SCANNING); + m_MsgDlg.m_WaitMsg.LoadString(IDS_PLEASE_WAIT_MSG); + m_MsgDlg.Create(IDD_MSG_DLG,this); + m_MsgDlg.ShowWindow(SW_SHOW); + m_MsgDlg.UpdateData(FALSE); + + m_audio_list.ResetContent(); + detect_sound_cards(1); + + // Remove the scanning window + m_MsgDlg.DestroyWindow(); + + for (i=0; i= Num_cards)) { + current = 0; + } + + // See if the chosen card supports direct sound 16 bit + if(Cards[current].mixers & DS16BIT_MIXER) + ds16_supported=TRUE; + else + ds16_supported=FALSE; + + os_config_write_string(szSectionName, "SoundcardName", Cards[current].name); + + int mixer_id; + mixer_id=GetMixerButton(); + + // For Chris, make DS8 be the mixer if user has a card selected + // (other than No sound) and no sound mixers could be detected for + // the device + if(current>0 && mixer_id==SOUND_MIXER_NONE) + mixer_id=SOUND_MIXER_DS_8; + + // If user has ds16 support, and has chosen direct sound, use it + if(mixer_id==SOUND_MIXER_DS_8 && ds16_supported) + mixer_id=SOUND_MIXER_DS_16; + + // Write out the default mixer + os_config_write_uint(NULL, "SoundMixer", mixer_id); + + // Write out the Launcher sound setting + LauncherSoundEnabled=m_LauncherSndCheck.GetCheck(); + os_config_write_uint(szSectionName, "LauncherSoundEnabled", LauncherSoundEnabled); + + CPropertyPage::OnOK(); +} + +BOOL CAudioTab::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + // TODO: Add extra initialization here + char *current_card; + int i, current; + int allow_user_to_choose_ds3d = 0; + UINT mixer_id; + + // Set the wait cursor + CWaitCursor wc; + + // Clear the box + m_audio_list.ResetContent(); + + // Display the scanning window + m_MsgDlg.m_ScanningMsg.LoadString(IDS_AUDIOTAB_SCANNING); + m_MsgDlg.m_WaitMsg.LoadString(IDS_PLEASE_WAIT_MSG); + m_MsgDlg.Create(IDD_MSG_DLG,this); + m_MsgDlg.ShowWindow(SW_SHOW); + m_MsgDlg.UpdateData(FALSE); + + // Detect all cards and fill the list + detect_sound_cards(1); + for (i=0; i0) { + current=0; + } + + if (current < 0) { + current = Num_cards - 1; + mixer_id=DetermineDefaultMixer(current); + } + + // If it's the first time since install, autodetect the best card + if(theApp.m_straight_to_setup) { + current=DetermineBestCard(); + mixer_id=DetermineDefaultMixer(current); + } + + // Set the current selection and available mixers + m_audio_list.SetCurSel(current); + EnableMixerSettings(Cards[current].mixers); + + SetMixerButton(mixer_id,Cards[current].mixers); + + // Set the Launcher sound check button if necessary + LauncherSoundEnabled = os_config_read_uint(szSectionName, "LauncherSoundEnabled", 1); + m_LauncherSndCheck.SetCheck(LauncherSoundEnabled); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +void CAudioTab::OnSelchangeAudioList() +{ + // TODO: Add your control notification handler code here + int index; + index=m_audio_list.GetCurSel(); + if(index!=CB_ERR && index= Cards[card_pos].mixers) card_pos=j; + + return(card_pos); +} + + +// Enables/disables mixer options according to given mixer flags +void CAudioTab::EnableMixerSettings(UINT mixers) +{ + HWND hwnd; + + GetDlgItem(IDC_MIXER_SOFTWARE,&hwnd); + ::EnableWindow(hwnd, mixers & SOFTWARE_MIXER); + + GetDlgItem(IDC_MIXER_DS8BIT,&hwnd); + ::EnableWindow(hwnd, mixers & DS8BIT_MIXER); + +/* We're not handling directsound 8 or 16 visually anymore + GetDlgItem(IDC_MIXER_DS16BIT,&hwnd); + ::EnableWindow(hwnd, mixers & DS16BIT_MIXER); +*/ + + GetDlgItem(IDC_MIXER_DS3D,&hwnd); + ::EnableWindow(hwnd, mixers & DS3D_MIXER); + + GetDlgItem(IDC_MIXER_AUREAL,&hwnd); + ::EnableWindow(hwnd, mixers & AUREAL_MIXER); + + GetDlgItem(IDC_MIXER_EAX,&hwnd); + ::EnableWindow(hwnd, mixers & EAX_MIXER); +} + +// selects the radio button corresponding to given registry ID +void CAudioTab::SetMixerButton(int mixer_id, UINT mixer_flags) +{ + // Turn them all off + ((CButton *) GetDlgItem(IDC_MIXER_SOFTWARE))->SetCheck(0); + ((CButton *) GetDlgItem(IDC_MIXER_DS16BIT))->SetCheck(0); + ((CButton *) GetDlgItem(IDC_MIXER_DS8BIT))->SetCheck(0); + ((CButton *) GetDlgItem(IDC_MIXER_DS3D))->SetCheck(0); + ((CButton *) GetDlgItem(IDC_MIXER_AUREAL))->SetCheck(0); + ((CButton *) GetDlgItem(IDC_MIXER_EAX))->SetCheck(0); + + // Now, check the appropriate one + switch(mixer_id) { + case SOUND_MIXER_SOFTWARE_16: + if(mixer_flags & SOFTWARE_MIXER) + ((CButton *) GetDlgItem(IDC_MIXER_SOFTWARE))->SetCheck(1); + break; + + // Now set and DS mixer to Default + case SOUND_MIXER_DS_16: + if(mixer_flags & DS16BIT_MIXER) + ((CButton *) GetDlgItem(IDC_MIXER_DS8BIT))->SetCheck(1); + break; + + case SOUND_MIXER_DS_8: + if(mixer_flags & DS8BIT_MIXER) + ((CButton *) GetDlgItem(IDC_MIXER_DS8BIT))->SetCheck(1); + break; + + case SOUND_MIXER_DS3D_16: + if(mixer_flags & DS3D_MIXER) + ((CButton *) GetDlgItem(IDC_MIXER_DS3D))->SetCheck(1); + break; + case SOUND_MIXER_AUREAL_16: + if(mixer_flags & AUREAL_MIXER) + ((CButton *) GetDlgItem(IDC_MIXER_AUREAL))->SetCheck(1); + break; + case SOUND_MIXER_EAX: + if(mixer_flags & EAX_MIXER) + ((CButton *) GetDlgItem(IDC_MIXER_EAX))->SetCheck(1); + break; + } +} + +// Returns the registry ID for the selected radio button +int CAudioTab::GetMixerButton(void) +{ + int mixer_id=SOUND_MIXER_NONE; + + if ( ((CButton *) GetDlgItem(IDC_MIXER_SOFTWARE))->GetCheck() == 1 ) + mixer_id=SOUND_MIXER_SOFTWARE_16; +/* + else if ( ((CButton *) GetDlgItem(IDC_MIXER_DS16BIT))->GetCheck() == 1 ) + mixer_id=SOUND_MIXER_DS_16; +*/ + else if ( ((CButton *) GetDlgItem(IDC_MIXER_DS8BIT))->GetCheck() == 1 ) + mixer_id=SOUND_MIXER_DS_8; + else if ( ((CButton *) GetDlgItem(IDC_MIXER_DS3D))->GetCheck() == 1 ) + mixer_id=SOUND_MIXER_DS3D_16; + else if ( ((CButton *) GetDlgItem(IDC_MIXER_AUREAL))->GetCheck() == 1 ) + mixer_id=SOUND_MIXER_AUREAL_16; + else if ( ((CButton *) GetDlgItem(IDC_MIXER_EAX))->GetCheck() == 1 ) + mixer_id=SOUND_MIXER_EAX; + + return(mixer_id); +} + +// Returns the default mixer for a given card index +UINT CAudioTab::DetermineDefaultMixer(int card_index) +{ + int mixer_type; + + // make 8 bit direct sound the generic default + mixer_type=SOUND_MIXER_DS_8; + + // make sure index is valid + if(card_index<0 || card_index>=Num_cards) + return(mixer_type); + + // if mixer supports software, make it the default + if(Cards[card_index].mixers & SOFTWARE_MIXER) + mixer_type=SOUND_MIXER_SOFTWARE_16; + +#ifdef OEM_AUREAL2 + // make aureal the default if it's available + if(Cards[card_index].mixers & AUREAL_MIXER) + mixer_type=SOUND_MIXER_AUREAL_16; +#endif + + return(mixer_type); +} + +// Display the html help file +BOOL CAudioTab::OnHelpInfo(HELPINFO* pHelpInfo) +{ +#ifdef USE_HTML_HELP_SYSTEM + CWaitCursor wc; + help_launch(AUDIOTAB_HELP); + return 1; +#else + return CPropertyPage::OnHelpInfo(pHelpInfo); +#endif +} + +// Display the html help file +afx_msg LRESULT CAudioTab::OnCommandHelp(WPARAM wParam, LPARAM lParam) +{ +#ifdef USE_HTML_HELP_SYSTEM + help_launch(AUDIOTAB_HELP); + return 1; +#else + return CPropertyPage::OnCommandHelp(wParam,lParam); +#endif +} + diff --git a/D3Launch/AudioTab.h b/D3Launch/AudioTab.h new file mode 100644 index 00000000..bd4a717f --- /dev/null +++ b/D3Launch/AudioTab.h @@ -0,0 +1,103 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/AudioTab.h $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 9 10/21/98 4:51p Nate + * More fixes. + * + * 8 10/15/98 11:31a Nate + * Added Launcher Sound toggling + * + * 7 10/14/98 5:52p Nate + * More fixes + * + * 6 10/10/98 4:05p Nate + * Added detection/scanning window messages + * + * 5 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 4 9/01/98 7:15p Nate + * Major Revision #2 + * + * 3 8/31/98 6:44p Nate + * Major Revision + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +#if !defined(AFX_AUDIOTAB_H__FAB3D182_22D6_11D2_8CBD_00A0C96ED60D__INCLUDED_) +#define AFX_AUDIOTAB_H__FAB3D182_22D6_11D2_8CBD_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// AudioTab.h : header file +// + +#include "MsgDlg.h" + +///////////////////////////////////////////////////////////////////////////// +// CAudioTab dialog + +class CAudioTab : public CPropertyPage +{ + DECLARE_DYNCREATE(CAudioTab) + +// Construction +public: + CAudioTab(); + ~CAudioTab(); + void EnableMixerSettings(UINT mixers); + int GetMixerButton(void); + void SetMixerButton(int mixer_id, UINT mixer_flags); + UINT DetermineDefaultMixer(int card_index); + int DetermineBestCard(void); + + CMsgDlg m_MsgDlg; + +// Dialog Data + //{{AFX_DATA(CAudioTab) + enum { IDD = IDD_PROPPAGE_AUDIO }; + CButton m_LauncherSndCheck; + CComboBox m_audio_list; + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CAudioTab) + public: + virtual void OnOK(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CAudioTab) + afx_msg void OnBtnAudioDetect(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeAudioList(); + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); + afx_msg LRESULT OnCommandHelp(WPARAM wParam, LPARAM lParam); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_AUDIOTAB_H__FAB3D182_22D6_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/BitmapButtonEx.cpp b/D3Launch/BitmapButtonEx.cpp new file mode 100644 index 00000000..e8c5414a --- /dev/null +++ b/D3Launch/BitmapButtonEx.cpp @@ -0,0 +1,502 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/BitmapButtonEx.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 25 11/05/98 2:16p Nate + * Added keyboard support + * + * 24 10/30/98 12:09p Nate + * Fixed clicking on light problem. + * + * 23 10/18/98 5:53p Nate + * + * 22 10/08/98 6:23p Nate + * Fixed a few bugs. + * + * 21 10/02/98 7:08p Nate + * Added animation button support. + * + * 20 10/01/98 11:51a Nate + * Fixed the 256-color text problem (finally...) + * + * 19 9/30/98 5:21p Nate + * + * 18 9/22/98 12:12p Nate + * Fixed logo text problem. + * + * 17 9/22/98 11:33a Nate + * Added support for logo button text. + * + * 16 9/18/98 6:47p Nate + * + * 15 9/18/98 6:32p Nate + * + * 14 9/18/98 5:19p Nate + * Made the bitmap button font look a *little* better + * + * 13 9/14/98 3:55p Nate + * Removed debugging output from Button drawing + * + * 12 9/14/98 3:48p Nate + * DrawItem now uses a CClientDC, and AutoLoad is no longer needed (Setup + * now handles all necessary attachment and sizing tasks) + * + * 11 9/13/98 2:39p Nate + * Added re-selecting of default bitmaps and palettes for the device + * contexts. + * + * 10 9/10/98 5:17p Nate + * Added text messages which can be drawn on top of the button. + * + * 9 9/03/98 6:57p Nate + * Fixed StretchBlt() problem by doing some 256 color conversions + * + * 8 9/02/98 6:41p Nate + * Sped up button drawing in 256 color + * + * 7 9/01/98 7:15p Nate + * Major Revision #2 + * + * 6 8/31/98 6:44p Nate + * Major Revision + * + * 5 8/24/98 7:06p Nate + * Added new AutoUpdate features, and fixed display glitches + * + * 4 8/12/98 9:21a Nate + * Fixed "gray-button-background" flicker + * + * 3 8/10/98 10:44a Nate + * Added Language selection support + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +// BitmapButtonEx.cpp : implementation file +// + +#include "stdafx.h" +#include "D3Launch.h" +#include "BitmapButtonEx.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// Text position values for the standard option button +#define LEFTBUTTON_TEXT_XOFFSET 85 +#define RIGHTBUTTON_TEXT_XOFFSET 85 +#define BUTTON_TEXT_YOFFSET 17 +#define BUTTON_TEXT_WIDTH 132 +#define BUTTON_TEXT_HEIGHT 17 + +// Text position values for the logo button +#define TOPBUTTON_TEXT_XOFFSET 86 +#define TOPBUTTON_TEXT_YOFFSET 80 +#define TOPBUTTON_TEXT_WIDTH 135 +#define TOPBUTTON_TEXT_HEIGHT 17 + +// Define text colors for button states +#define UP_TEXT_COLOR PALETTERGB(162,167,204) +#define UP_TEXT_SHADOW_COLOR PALETTERGB(139,146,190) +#define DOWN_TEXT_COLOR PALETTERGB(255,255,255) +#define DOWN_TEXT_SHADOW_COLOR PALETTERGB(192,192,192) +#define LIT_TEXT_COLOR PALETTERGB(255,255,255) +#define LIT_TEXT_SHADOW_COLOR PALETTERGB(192,192,192) +#define DISABLED_TEXT_COLOR PALETTERGB(128,128,128) +#define DISABLED_TEXT_SHADOW_COLOR PALETTERGB(128,128,128) + + +///////////////////////////////////////////////////////////////////////////// +// CBitmapButtonEx + +CBitmapButtonEx::CBitmapButtonEx() +{ + m_MouseOverBtn=FALSE; + m_Hidden=FALSE; + + m_TextMessage=""; // Default to no string message + m_Orientation=LEFT_ORIENTED_BTN; // Default to left orientation + + m_AnimBitmaps=NULL; + m_NumAnimFrames=0; + m_CurrAnimFrame=0; + m_IgnoreDisabled=FALSE; +} + +CBitmapButtonEx::~CBitmapButtonEx() +{ + // Delete the allocated bitmaps + if(m_AnimBitmaps!=NULL) delete[] m_AnimBitmaps; + + // Detach this from the button object + Detach(); +} + + +BEGIN_MESSAGE_MAP(CBitmapButtonEx, CBitmapButton) + //{{AFX_MSG_MAP(CBitmapButtonEx) + ON_WM_ERASEBKGND() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBitmapButtonEx message handlers + +// Draw the button +void CBitmapButtonEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) +{ + // TODO: Add your code to draw the specified item + CBitmap *bitmap; + CPalette *palette; + COLORREF old_color, new_color, new_shadow_color; + CFont *old_font=NULL; + CBitmap *old_bitmap=NULL; + CPalette *old_palette=NULL; + int old_mode=0; + UINT old_alignment=0; + + // If button is hidden, don't draw it + if(m_Hidden) return; + + // Get button's state and draw appropriate bitmap + if(m_AnimBitmaps!=NULL) { + bitmap=&m_AnimBitmaps[m_CurrAnimFrame]; + new_color=DOWN_TEXT_COLOR; + new_shadow_color=DOWN_TEXT_SHADOW_COLOR; + } + else if(lpDrawItemStruct->itemState & ODS_SELECTED) { + bitmap=&m_DownBitmap; + new_color=DOWN_TEXT_COLOR; + new_shadow_color=DOWN_TEXT_SHADOW_COLOR; + } + else if(!m_IgnoreDisabled && lpDrawItemStruct->itemState & ODS_DISABLED) { + bitmap=&m_DisabledBitmap; + new_color=DISABLED_TEXT_COLOR; + new_shadow_color=DISABLED_TEXT_SHADOW_COLOR; + } + else if(m_MouseOverBtn || lpDrawItemStruct->itemState & ODS_FOCUS) { + bitmap=&m_MouseBitmap; + new_color=LIT_TEXT_COLOR; + new_shadow_color=LIT_TEXT_SHADOW_COLOR; + } + else { + bitmap=&m_UpBitmap; + new_color=UP_TEXT_COLOR; + new_shadow_color=UP_TEXT_SHADOW_COLOR; + } + + // Use the Application default palette (speeds things up in 256 color) + palette=&theApp.m_palette; + + //RECT rect=lpDrawItemStruct->rcItem; + + // Obtain the client window for this button + CClientDC *dc; + try { + dc=new CClientDC(this); + } + catch(CResourceException) { + OutputDebugString("Could not get ClientDC for bitmap button!\n"); + } + + CDC memDC; + + CRect crect; + GetClientRect(&crect); + + BITMAP m_bmInfo; // Bitmap info + bitmap->GetObject(sizeof(BITMAP), &m_bmInfo); + + // Select and realize the palette + if( dc->GetDeviceCaps(RASTERCAPS) & RC_PALETTE && palette->m_hObject != NULL ) { + old_palette=dc->SelectPalette( palette, TRUE ); + dc->RealizePalette(); + } + + if(memDC.CreateCompatibleDC(dc)==0) + OutputDebugString("CreateCompatibleDC() failed.\n"); + + if((old_bitmap=memDC.SelectObject( bitmap )) == NULL) + OutputDebugString("SelectObject() failed!\n"); + + dc->StretchBlt( 0, 0,crect.Width(),crect.Height(), &memDC, 0, 0, m_bmInfo.bmWidth,m_bmInfo.bmHeight,SRCCOPY ); + + // If the button contains a text message, display it + if(!m_TextMessage.IsEmpty()) { + + //old_font = (CFont *)dc->SelectStockObject( ANSI_VAR_FONT ); + old_font = dc->SelectObject( &m_btn_font ); + old_mode=dc->SetBkMode(TRANSPARENT); + old_alignment=dc->SetTextAlign(TA_CENTER | TA_TOP); + old_color=dc->SetTextColor(new_shadow_color); + + dc->ExtTextOut( m_TextStartPoint.x-1,m_TextStartPoint.y, + ETO_CLIPPED,&m_TextClipBox,m_TextMessage,NULL); + dc->SetTextColor(new_color); + + //dc->Rectangle(&m_TextClipBox); + dc->ExtTextOut( m_TextStartPoint.x,m_TextStartPoint.y, + ETO_CLIPPED,&m_TextClipBox,m_TextMessage,NULL); + //dc->DrawText(m_TextMessage,&m_TextClipBox,DT_CENTER); + + dc->SetTextColor(old_color); + dc->SetTextAlign(old_alignment); + dc->SetBkMode(old_mode); + + if(old_font!=NULL) + dc->SelectObject(old_font); + } + + if(old_bitmap!=NULL) + memDC.SelectObject(old_bitmap); + + if(old_palette!=NULL) + dc->SelectPalette(old_palette,FALSE); + + if(memDC.DeleteDC()==0) + OutputDebugString("DeleteDC() failed!\n"); + + delete dc; + + //CBitmapButton::DrawItem(lpDrawItemStruct); +} + +// Sets up the button for use +bool CBitmapButtonEx::Setup(UINT nID, CWnd *parent, int orient /*=LEFT_ORIENTED_BTN*/) +{ + CString res_name, title; + + if(parent==NULL) return FALSE; + + // Let the bitmap class set things up for us + // NOTE:this function will also cause a redundant loading of bitmaps + // since CBitmapButton will store copies for itself, however, + // it is this funciton which automatically sets up the button's + // size, position, etc. from the resources... + //AutoLoad(nID,parent); + + // Attach this button instance to the proper button resource + HWND hwnd; + parent->GetDlgItem(nID,&hwnd); + if(Attach(hwnd)==0) + OutputDebugString("Attach() failed!\n"); + + // Setup the text alignment values + m_Orientation = orient; + + // Fill in text parameters for different button orientations + int width, height; + if(m_Orientation==TOP_ORIENTED_BTN) { + + // top oriented button + m_TextStartPoint.x=int(TOPBUTTON_TEXT_XOFFSET*DlgWidthModifier); + m_TextStartPoint.y=int(TOPBUTTON_TEXT_YOFFSET*DlgHeightModifier); + + width=int(TOPBUTTON_TEXT_WIDTH*DlgWidthModifier); + height=int(TOPBUTTON_TEXT_HEIGHT*DlgHeightModifier); + + } + else if(m_Orientation==LEFT_ORIENTED_BTN) { + + // left oriented button + m_TextStartPoint.x=int(LEFTBUTTON_TEXT_XOFFSET*DlgWidthModifier); + m_TextStartPoint.y=int(BUTTON_TEXT_YOFFSET*DlgHeightModifier); + + width=int(BUTTON_TEXT_WIDTH*DlgWidthModifier); + height=int(BUTTON_TEXT_HEIGHT*DlgHeightModifier); + + } + else { + + // right oriented button + m_TextStartPoint.x=int(RIGHTBUTTON_TEXT_XOFFSET*DlgWidthModifier); + m_TextStartPoint.y=int(BUTTON_TEXT_YOFFSET*DlgHeightModifier); + + width=int(BUTTON_TEXT_WIDTH*DlgWidthModifier); + height=int(BUTTON_TEXT_HEIGHT*DlgHeightModifier); + } + + // Now compute the text bounding box from the button parameters + m_TextClipBox.left=m_TextStartPoint.x - (width/2); + m_TextClipBox.top=m_TextStartPoint.y; + + m_TextClipBox.right=m_TextClipBox.left+width; + m_TextClipBox.bottom=m_TextClipBox.top+height; + + // Set the font for the normal option buttons + m_btn_font.CreateFont( + int(14*DlgHeightModifier), + int(8*DlgWidthModifier), + 0, 0, 0, 0, 0, 0, 0, + 0, 0, PROOF_QUALITY, + 0, _T("Arial Bold") ); + + // Set the font for the logo buttons + m_logobtn_font.CreateFont( + int(14*DlgHeightModifier), + int(8*DlgWidthModifier), + 0, 0, 0, 0, 0, 0, 0, + 0, 0, PROOF_QUALITY, + 0, _T("Arial Bold") ); + + // Load the bitmaps and palettes that we will use + Load(nID,parent); + + // Resize the buttons to match the proportions of the dialog + BITMAP bm; + m_UpBitmap.GetObject(sizeof(BITMAP), &bm); + SetWindowPos(NULL,0,0,int(bm.bmWidth*DlgWidthModifier),int(bm.bmHeight*DlgHeightModifier),SWP_NOMOVE|SWP_NOZORDER); + + return TRUE; +} + + +// Sets up the animation button for use +bool CBitmapButtonEx::AnimSetup(UINT nID, CWnd *parent, int num_frames) +{ + CString res_name, title; + + if(num_frames==0) return FALSE; + + if(parent==NULL) return FALSE; + + // Let the bitmap class set things up for us + // NOTE:this function will also cause a redundant loading of bitmaps + // since CBitmapButton will store copies for itself, however, + // it is this funciton which automatically sets up the button's + // size, position, etc. from the resources... + //AutoLoad(nID,parent); + + // Set the number of frames + m_NumAnimFrames=num_frames; + + // Attach this button instance to the proper button resource + HWND hwnd; + parent->GetDlgItem(nID,&hwnd); + if(Attach(hwnd)==0) + OutputDebugString("Attach() failed!\n"); + + // Load the bitmaps and palettes that we will use + AnimLoad(nID,parent); + + // Resize the buttons to match the proportions of the dialog + BITMAP bm; + m_AnimBitmaps[0].GetObject(sizeof(BITMAP), &bm); + SetWindowPos(NULL,0,0,int(bm.bmWidth*DlgWidthModifier),int(bm.bmHeight*DlgHeightModifier),SWP_NOMOVE|SWP_NOZORDER); + + return TRUE; +} + + +// Loads the bitmaps for the button given +// U - up position +// D - down position +// M - lit (mouse is over it) position +// X - disabled +bool CBitmapButtonEx::Load(UINT nID, CWnd *parent) +{ + CString res_name, title; + + if(parent==NULL) return FALSE; + + parent->GetDlgItemText(nID, title); + + OutputDebugString("title ="); + OutputDebugString(title); + OutputDebugString("\n"); + + res_name.Format("%s%s",title,"U"); + GetBitmapAndPalette(res_name,&m_UpBitmap,NULL); + res_name.Format("%s%s",title,"D"); + GetBitmapAndPalette(res_name,&m_DownBitmap,NULL); + res_name.Format("%s%s",title,"M"); + GetBitmapAndPalette(res_name,&m_MouseBitmap,NULL); + res_name.Format("%s%s",title,"X"); + GetBitmapAndPalette(res_name,&m_DisabledBitmap,NULL); + + return(TRUE); +} + +// Loads the animation bitmaps for the button given +// Format: nameX where X is the frame # +bool CBitmapButtonEx::AnimLoad(UINT nID, CWnd *parent) +{ + CString res_name, title; + int j; + + if(parent==NULL) return FALSE; + + parent->GetDlgItemText(nID, title); + + OutputDebugString("title ="); + OutputDebugString(title); + OutputDebugString("\n"); + + // Allocate bitmap objects + if(m_NumAnimFrames==0) return FALSE; + m_AnimBitmaps=new CBitmap[m_NumAnimFrames]; + if(m_AnimBitmaps==NULL) return FALSE; + + // Load in the bitmaps + for(j=0; j= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +// BitmapButtonEx.h : header file +// + +// Button orientation values (only used for option button text alignment) +#define LEFT_ORIENTED_BTN 0 +#define RIGHT_ORIENTED_BTN 1 +#define TOP_ORIENTED_BTN 2 + + +///////////////////////////////////////////////////////////////////////////// +// CBitmapButtonEx window + +class CBitmapButtonEx : public CBitmapButton +{ +// Construction +public: + CBitmapButtonEx(); + +// Attributes +public: + // Button state bitmaps + CBitmap m_UpBitmap; + CBitmap m_DownBitmap; + CBitmap m_DisabledBitmap; + CBitmap m_MouseBitmap; + + // Bitmaps for an animated button (doesn't behave as a button however) + CBitmap *m_AnimBitmaps; + int m_NumAnimFrames; + int m_CurrAnimFrame; + +private: + CString m_TextMessage; // The text to be displayed over the button + RECT m_TextClipBox; // The clipping rectangle for the text + POINT m_TextStartPoint; // The starting point offset for the text + + bool m_MouseOverBtn; // Is the mouse currently over the button? + bool m_Hidden; // Is the button hidden? + int m_Orientation; // Is the button a left or right option button + + CFont m_btn_font; // Font to be used by the button text + CFont m_logobtn_font; // Font to be used by the logo buttons + + bool m_IgnoreDisabled; // Allows buttons to be disabled functionality-wise, + // but not bitmap-wise + +// Operations +public: + // Sets up and loads the hi-color bitmaps and palettes + bool Setup(UINT nID, CWnd *parent, int orient=LEFT_ORIENTED_BTN); + bool AnimSetup(UINT nID, CWnd *parent, int num_frames); + + bool Load(UINT nID, CWnd *parent); // Loads the hi-color bitmaps and palettes + bool AnimLoad(UINT nID, CWnd *parent); // Loads bitmaps for animation + void Light(bool bLight); // Lights/un-Lights the button + void Hide(bool bHide); // Hides/un-Hides a button + void SetText(UINT nID); // Sets the button's text message + void DoNextAnimFrame(void); // Points button to next animation frame + + bool IsLit(void) { return(m_MouseOverBtn); } // checks if button is lit + bool IsHidden(void) { return(m_Hidden); } // checks if button is hidden + + void IgnoreDisabled(bool value) { m_IgnoreDisabled=value; } // sets the ignore disabled flag + + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBitmapButtonEx) + public: + virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CBitmapButtonEx(); + + // Generated message map functions +protected: + //{{AFX_MSG(CBitmapButtonEx) + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BITMAPBUTTONEX_H__04FA7822_2AB0_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/D3Launch.cpp b/D3Launch/D3Launch.cpp new file mode 100644 index 00000000..9c79e019 --- /dev/null +++ b/D3Launch/D3Launch.cpp @@ -0,0 +1,1197 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/D3Launch.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 45 8/20/99 9:54a Nate + * Full OEM Release now calls Ereg + * + * 44 8/19/99 6:13p Samir + * detect vortex1 chipsets. + * + * 43 6/17/99 5:52p Nate + * Fixed bug with Italian Help File copying + * + * 42 6/09/99 2:46p Nate + * Minor changes for different builds + * + * 41 5/26/99 5:07a Nate + * Fixed static OLE dll linking problem + * + * 40 5/23/99 11:44a Nate + * Added change to make sure the DDraw dll gets freed when launcher exits. + * + * 39 5/21/99 3:38p Nate + * Added changes for Rest of World release (new update directory path) + * + * 38 5/19/99 12:29p Nate + * Fixed openGL crash, changed Network speed default, changed OpenGL + * detection to default to unchecked, and removed config file parsing from + * US version + * + * 37 5/07/99 11:23a Nate + * Added support for a launcher config file + * + * 36 4/27/99 10:42p Nate + * Added vsync enabling when direct3d is chosen + * + * 35 4/15/99 12:03p Nate + * Added "Descent 3 Demo 2" build type + * + * 34 4/08/99 1:13p Nate + * Added Pentium III detection + * + * 33 3/19/99 10:18a Nate + * Added OEM_GENERIC compile type + * + * 32 3/15/99 3:05p Nate + * Added fix to multi-language help system + * + * 31 3/12/99 3:29p Nate + * Added more multi-language support + * + * 30 3/02/99 5:45p Nate + * Lots of little changes/fixes + * + * 29 2/26/99 12:50p Nate + * Changed OEM_Voodoo3 names + * + * 28 2/24/99 8:37p Nate + * Various little dialog changes, added "Install Drivers" dialog + * + * 27 2/24/99 1:46p Nate + * Added multi-language support + * + * 26 2/22/99 4:05p Nate + * Made GLU32 fix only for demo version + * + * 25 2/15/99 5:46p Nate + * Made StraightToSetup default to TRUE if it's not in registry at all + * + * 24 2/15/99 1:41p Nate + * Added DirectX installation through DirectSetup + * + * 23 2/12/99 5:00p Nate + * Added some satellite resource DLL test code + * + * 22 1/21/99 11:12a Nate + * Added hacked fix to the Glu32.dll problem + * + * 21 11/30/98 3:00p Nate + * Added StringToLower() + * + * 20 10/21/98 12:10p Nate + * + * 19 10/16/98 3:26p Nate + * + * 18 10/15/98 7:30p Nate + * + * 17 10/15/98 11:31a Nate + * Added Launcher Sound toggling + * + * 16 10/14/98 11:37a Nate + * Added CoInitialize() call for App + * + * 15 10/08/98 6:23p Nate + * Fixed a few bugs. + * + * 14 9/30/98 1:59p Nate + * Added Version constants for demo and full builds + * + * 13 9/29/98 6:05p Nate + * Added the functionality to update the game version from a text file. + * + * 12 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 11 9/16/98 3:23p Nate + * Added m_straight_to_setup detection + * + * 10 9/14/98 3:47p Nate + * Added deletion of memDC's after use. + * + * 9 9/13/98 2:40p Nate + * Added re-selecting of default bitmaps and palettes for the device + * contexts. + * + * 8 9/03/98 6:57p Nate + * Fixed StretchBlt() problem by doing some 256 color conversions + * + * 7 9/02/98 6:42p Nate + * Added improved sound support. + * + * 6 9/01/98 7:15p Nate + * Major Revision #2 + * + * 5 8/31/98 6:44p Nate + * Major Revision + * + * 4 8/24/98 7:06p Nate + * Added new AutoUpdate features, and fixed display glitches + * + * 3 8/10/98 10:44a Nate + * Added Language selection support + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +// D3Launch.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "mmsystem.h" +#include "D3Launch.h" +#include "D3LaunchDlg.h" +#include "LaunchNames.h" +#include "3D_detect.h" +#include "OS_Config.h" +#include +#include +#include +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// Launcher config file options +bool LanguageSelectionEnabled; +bool EregEnabled; + +// Launcher sound on/off flag +int LauncherSoundEnabled; + +// Declare setup flags +bool VideoCardsDetected; +bool DetailLevelConfigured; +bool NewLanguageSelected; +bool RenderersDetected; + +// Flag which indicates if grGlideInit() has been called +bool GlideInited; + +// Global storage for DirectX version number +int Dx_version; + +// Global storage for DDraw handle +HINSTANCE Dd_dll_handle=NULL; + +// Global storage for OpenGL library +HINSTANCE opengl_dll_handle=NULL; + +// Values to scale the bitmaps to match the dialog size +double DlgWidthModifier; +double DlgHeightModifier; + +// Function to update the game Version after a manual patch +bool ProcessUpdatedVersionFile(void); + +// Function to see if user needs Glu32.dll +bool ProcessGlu32DLL(void); + +///////////////////////////////////////////////////////////////////////////// +// CD3LaunchApp + +BEGIN_MESSAGE_MAP(CD3LaunchApp, CWinApp) + //{{AFX_MSG_MAP(CD3LaunchApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CD3LaunchApp construction + +CD3LaunchApp::CD3LaunchApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance + m_straight_to_update = 0; + m_hResInst=NULL; + m_hDefResInst=NULL; +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CD3LaunchApp object + +CD3LaunchApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CD3LaunchApp initialization + +BOOL CD3LaunchApp::FirstInstance() +{ + HANDLE hnd; + + // See if the D3 Launcher mutex has already been created + hnd=OpenMutex(MUTEX_ALL_ACCESS,FALSE,D3_LAUNCHER_MUTEX_NAME); + if(hnd==NULL) + return TRUE; // Nope, this is the first instance + + // close the mutex handle + CloseHandle(hnd); + + // Determine if another window with our title exists... + CWnd *pWndPrev, *pWndChild; + pWndPrev = CWnd::FindWindow(NULL,szTitle ); + if (pWndPrev) + { + // if so, does it have any popups? + pWndChild = pWndPrev->GetLastActivePopup(); + + // If iconic, restore the main window + if (pWndPrev->IsIconic()) + pWndPrev->ShowWindow(SW_RESTORE); + + // Bring the main window or its popup to + // the foreground + pWndChild->SetForegroundWindow(); + } + + // and we are done activating the previous one. + return FALSE; +} + +// parse for special (outrage) command-line arguments +void CD3LaunchApp::OutrageParseCommandLine() +{ + // right now all we do is a direct string compare on the + // application object's + // command line var, for the "straight to update" argument + if(!strcmp(m_lpCmdLine, "-straight_to_update")){ + m_straight_to_update = 1; + } +} + +BOOL CD3LaunchApp::InitInstance() +{ + //AfxEnableControlContainer(); + + // Get a handle for the executable's resources (english) + m_hDefResInst=AfxGetResourceHandle(); + + // Get the title of the launcher + SetLauncherTitleString(); + + // If a previous instance of the application is already running, + // then activate it and return FALSE from InitInstance to + // end the execution of this instance. + if(!FirstInstance()){ + return FALSE; + } + + // Create the Mutex to signal that the Launcher is currently running + if(CreateMutex(NULL,TRUE,D3_LAUNCHER_MUTEX_NAME)==NULL) { + return FALSE; + } + + // Initialize the com object for this ap + CoInitialize(NULL); + + // parse the command line + OutrageParseCommandLine(); + + // check to see if the Setup dialog should be displayed right away + m_straight_to_setup = (UINT)os_config_read_uint(szSectionName, "StraightToSetup", 1); + + // check to see if the launcher sound is enabled + LauncherSoundEnabled = os_config_read_uint(szSectionName, "LauncherSoundEnabled", 1); + + // check for an updated version text file + ProcessUpdatedVersionFile(); + + // Setup Config Defaults for Releases +#if (defined(FULL_US_RELEASE) || defined(FULL_AUSSIE_RELEASE) || defined(OEM_GENERIC)) + LanguageSelectionEnabled=FALSE; + EregEnabled=TRUE; +#elif (defined(FULL_ROW_RELEASE) && !defined(INITIAL_UK_RELEASE)) + LanguageSelectionEnabled=TRUE; + EregEnabled=FALSE; +#elif (defined(FULL_ROW_RELEASE) && defined(INITIAL_UK_RELEASE)) + LanguageSelectionEnabled=FALSE; + EregEnabled=FALSE; +#else + LanguageSelectionEnabled=FALSE; + EregEnabled=FALSE; +#endif + +#ifdef DEMO + // see if user needs Glu32.dll + ProcessGlu32DLL(); +#endif + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + BOOL ret; + /* + // Get the application palette + ret = GetBitmapAndPalette(IDB_PALETTE_BITMAP,&m_bkBmap,&m_palette); + if ( !ret ) return TRUE; + + // Get the background bitmap + ret = GetBitmapAndPalette(IDB_D3LAUNCH_BG,&m_bkBmap,NULL); + if ( !ret ) return TRUE; + */ + + // Get the background bitmap + ret = GetBitmapAndPalette(IDB_D3LAUNCH_BG,&m_bkBmap,&m_palette); + if ( !ret ) return TRUE; + + // Nothing has been detected yet + VideoCardsDetected=FALSE; + DetailLevelConfigured=FALSE; + NewLanguageSelected=FALSE; + RenderersDetected=FALSE; + GlideInited=FALSE; + Dx_version=0; + Dd_dll_handle=NULL; + opengl_dll_handle=NULL; + + // Display the main menu dialog + CD3LaunchDlg dlg; + m_pMainWnd = &dlg; + int nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} + +int CD3LaunchApp::ExitInstance() +{ + // If glide has been initialized, shut it down before we exit + //shutdown_glide(); // don't need this now (it shuts it down in 3D_detect) + + if(m_hResInst!=NULL) { + FreeLibrary(m_hResInst); + m_hResInst=NULL; + } + + if(opengl_dll_handle!=NULL) { + FreeLibrary(opengl_dll_handle); + opengl_dll_handle=NULL; + } + + // Just in case, make sure the DDraw DLL has been freed + if (Dd_dll_handle!=NULL) { + FreeLibrary(Dd_dll_handle); + Dd_dll_handle=NULL; + } + + return CWinApp::ExitInstance(); +} + +// Launches user's web browser with appropriate file +#define HELP_DIR "hlp\\" +void help_launch(char *help_filename) +{ + char curr_dir[_MAX_PATH+1]; + char file_path[_MAX_PATH+1]; + + if(_getcwd(curr_dir,_MAX_PATH)==NULL) + return; + + sprintf(file_path,"%s\\%s%s",curr_dir,HELP_DIR,help_filename); + + // Make sure the help file exist + if( _access(file_path,0x00) == -1) { + CString nohelp_msg; + nohelp_msg.Format(IDS_D3LAUNCH_NO_HELP,file_path); + AfxMessageBox( nohelp_msg, MB_OK | MB_ICONEXCLAMATION); + return; + } + + // Display the help file + url_launch(file_path); +} + + +// Starts up user's web browser with the given URL +void url_launch(char *url) +{ + int r; + + r = (int) ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOW); + if (r < 32) { + CString txt; + switch (r) { + case 0: txt.LoadString(IDS_D3LAUNCH_URL_ERR1); break; + case ERROR_BAD_FORMAT: txt.LoadString(IDS_D3LAUNCH_URL_ERR2); break; + case SE_ERR_ACCESSDENIED: txt.LoadString(IDS_D3LAUNCH_URL_ERR3); break; + case SE_ERR_ASSOCINCOMPLETE: txt.LoadString(IDS_D3LAUNCH_URL_ERR4); break; + case SE_ERR_DDEBUSY: txt.LoadString(IDS_D3LAUNCH_URL_ERR5); break; + case SE_ERR_DDEFAIL: txt.LoadString(IDS_D3LAUNCH_URL_ERR6); break; + case SE_ERR_DDETIMEOUT: txt.LoadString(IDS_D3LAUNCH_URL_ERR7); break; + case SE_ERR_DLLNOTFOUND: txt.LoadString(IDS_D3LAUNCH_URL_ERR8); break; + case SE_ERR_OOM: txt.LoadString(IDS_D3LAUNCH_URL_ERR9); break; + case SE_ERR_SHARE: txt.LoadString(IDS_D3LAUNCH_URL_ERR10); break; + + // No browser installed message + case SE_ERR_NOASSOC: + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + txt.LoadString(IDS_D3LAUNCH_URL_ERR11); + break; + + default: txt.LoadString(IDS_D3LAUNCH_URL_ERR12); break; + } + AfxMessageBox(txt, MB_OK | MB_ICONERROR); + } +} + + +// Plays a sound (.wav resource) +BOOL PlayResource(LPSTR lpName, bool WaitUntilDone) +{ + BOOL bRtn; + LPSTR lpRes; + HANDLE hRes; + HRSRC hResInfo; + HINSTANCE Nl=AfxGetResourceHandle(); + + /* Find the WAVE resource. */ + hResInfo= FindResource(Nl,lpName,"WAVE"); + + if(hResInfo == NULL) + return FALSE; + + /* Load the WAVE resource. */ + hRes = LoadResource(Nl,hResInfo); + if (hRes == NULL) + return FALSE; + + /* Lock the WAVE resource and play it. */ + lpRes=(LPSTR)LockResource(hRes); + if(lpRes==NULL) + return FALSE; + + int play_type = (WaitUntilDone) ? SND_SYNC : SND_ASYNC; + + bRtn = sndPlaySound(lpRes, SND_MEMORY | play_type); + if(bRtn == NULL) + return FALSE; + + /* Free the WAVE resource and return success or failure. */ + FreeResource(hRes); + return TRUE; +} + + +// Assigns RGB values to a palette entry +BOOL SetPaletteEntry(PALETTEENTRY *pal_entry, BYTE red, BYTE green, BYTE blue) +{ + pal_entry->peRed = red; + pal_entry->peGreen = green; + pal_entry->peBlue = blue; + pal_entry->peFlags = 0; + + return TRUE; +} + + +// Loads a bitmap and palette from a given resource ID +BOOL GetBitmapAndPalette(UINT nIDResource, CBitmap *bitmap, CPalette *pal) +{ + LPCTSTR lpszResourceName = (LPCTSTR)nIDResource; + + return(GetBitmapAndPalette(lpszResourceName,bitmap,pal)); +} + + +// Loads a bitmap and palette from a given resource name +BOOL GetBitmapAndPalette(LPCTSTR lpszResourceName, CBitmap *bitmap, CPalette *pal) +{ + // Make sure a bitmap is given + if(bitmap==NULL) return TRUE; + + // Load in the bitmap resource + HBITMAP hBmp = (HBITMAP)::LoadImage( AfxGetResourceHandle(), + lpszResourceName, IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION ); + + if( hBmp == NULL ) + return FALSE; + + // Delete any attached objects from the bitmap + if(!bitmap->DeleteObject()) { + //OutputDebugString("DeleteObject() failed.\n"); + } + + // Attach the bitmap handle to the bitmap + bitmap->Attach( hBmp ); + + // If no palette is desired, get outta here + if(pal==NULL) return TRUE; + + // Delete any attached objects from the palette + if(!pal->DeleteObject()) { + //OutputDebugString("DeleteObject() failed.\n"); + } + + // Create a logical palette for the bitmap + DIBSECTION ds; + BITMAPINFOHEADER &bmInfo = ds.dsBmih; + bitmap->GetObject( sizeof(ds), &ds ); + + int nColors = bmInfo.biClrUsed ? bmInfo.biClrUsed : 1 << bmInfo.biBitCount; + + // Create a halftone palette if colors > 256. + CClientDC dc(NULL); // Desktop DC + + if( nColors > 256 ) + pal->CreateHalftonePalette( &dc ); + else { // Create the palette + RGBQUAD *pRGB = new RGBQUAD[nColors]; + if(pRGB==NULL) + return FALSE; + + CDC memDC; + CBitmap *old_bitmap=NULL; + + memDC.CreateCompatibleDC(&dc); + old_bitmap=memDC.SelectObject( bitmap ); + ::GetDIBColorTable( memDC, 0, nColors, pRGB ); + + if(old_bitmap!=NULL) + memDC.SelectObject(old_bitmap); + + if(memDC.DeleteDC()==0) + OutputDebugString("DeleteDC() failed!\n"); + + UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * 256); + LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize]; + if(pLP==NULL) { + delete[] pRGB; + return FALSE; + } + + pLP->palVersion = 0x300; + pLP->palNumEntries = 256; + + // Set the first 10 entries to default windows colors + SetPaletteEntry(&(pLP->palPalEntry[0]),0 ,0 ,0 ); // Black + SetPaletteEntry(&(pLP->palPalEntry[1]),128,0 ,0 ); // Dark Red + SetPaletteEntry(&(pLP->palPalEntry[2]),0 ,128,0 ); // Dark Green + SetPaletteEntry(&(pLP->palPalEntry[3]),128,128,0 ); // Dark Yellow + SetPaletteEntry(&(pLP->palPalEntry[4]),0 ,0 ,128); // Dark Blue + SetPaletteEntry(&(pLP->palPalEntry[5]),128,0 ,128); // Dark Magenta + SetPaletteEntry(&(pLP->palPalEntry[6]),0 ,128,128); // Dark Cyan + SetPaletteEntry(&(pLP->palPalEntry[7]),192,192,192); // Light Gray + SetPaletteEntry(&(pLP->palPalEntry[8]),192,220,192); // "money" Green + SetPaletteEntry(&(pLP->palPalEntry[9]),166,202,240); // "sky" Blue + + // Set the middle 236 entries to the first 236 entries of the palette + for( int i=0; i < 236; i++) { + if( i < nColors ) { + pLP->palPalEntry[i+10].peRed = pRGB[i].rgbRed; + pLP->palPalEntry[i+10].peGreen = pRGB[i].rgbGreen; + pLP->palPalEntry[i+10].peBlue = pRGB[i].rgbBlue; + pLP->palPalEntry[i+10].peFlags = 0; + } + else { + SetPaletteEntry(&(pLP->palPalEntry[i+10]),0,0,0); + } + } + + // Set the last 10 entries to default windows colors + SetPaletteEntry(&(pLP->palPalEntry[246]),255,251,240); // Cream + SetPaletteEntry(&(pLP->palPalEntry[247]),160,160,164); // Medium Gray + SetPaletteEntry(&(pLP->palPalEntry[248]),128,128,128); // Dark Gray + SetPaletteEntry(&(pLP->palPalEntry[249]),255,0 ,0 ); // Red + SetPaletteEntry(&(pLP->palPalEntry[250]),0 ,255,0 ); // Green + SetPaletteEntry(&(pLP->palPalEntry[251]),255,255,0 ); // Yellow + SetPaletteEntry(&(pLP->palPalEntry[252]),0 ,0 ,255); // Blue + SetPaletteEntry(&(pLP->palPalEntry[253]),255,0 ,255); // Magenta + SetPaletteEntry(&(pLP->palPalEntry[254]),0 ,255,255); // Cyan + SetPaletteEntry(&(pLP->palPalEntry[255]),255,255,255); // White + + // Create the palette + pal->CreatePalette( pLP ); + + delete[] pLP; + delete[] pRGB; + } + return TRUE; +} + + +#define MAX_MESSAGES 10 // max messages to process during a message deferral + +// Processes and waiting messages +void DeferMessages(void) +{ + MSG msg; + for ( int MsgCount = MAX_MESSAGES; + MsgCount && PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ); + MsgCount--) { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } +} + + + +// Function to see if user needs Glu32.dll +bool ProcessGlu32DLL(void) +{ + // First, see if Glu32.xyz is even in the directory + if(_access("Glu32.xyz",0) == -1) return FALSE; + + // Second, see if user's system already has access to a Glu32.dll + HINSTANCE dll_handle; + dll_handle=LoadLibrary("Glu32.dll"); + if(dll_handle!=NULL) { + FreeLibrary(dll_handle); + DeleteFile("Glu32.xyz"); + return FALSE; + } + + // Ok, user doesn't have it, so rename ours + rename("Glu32.xyz","Glu32.dll"); + return TRUE; +} + + +// Checks to see if a new version text file exists (such a file should +// only be created if the user does a manual patch update). If one is +// found, the version info is read from it. If this version is newer +// than the version stored in the registry, it is then written into +// the registry as the new game version. +bool ProcessUpdatedVersionFile(void) +{ + FILE *f; + uint cur_major, cur_minor, cur_build; + uint new_major, new_minor, new_build; + char buffer[PSPATHNAME_LEN+1]; + char verbuffer[PSPATHNAME_LEN+1]; + + // See if the updated version text file exists + f = fopen(UPDATED_VERSION_FNAME, "rt"); + if(f == NULL){ + return FALSE; + } + + // Read in the Version info from the text file + new_major=0; + new_minor=0; + new_build=0; + strcpy(buffer,""); + while (!feof(f)) { + + // Read the line into a temporary buffer + fgets(buffer, PSPATHNAME_LEN, f); + + // take the \n off the end of it + if(strlen(buffer)>0 && buffer[strlen(buffer) - 1] == '\n') + buffer[strlen(buffer) - 1] = 0; + + // If the line is empty, go get another one + if(strlen(buffer)==0) continue; + + // If the line is a comment, go get another one + if(buffer[0]==VERSION_FILE_COMMENT_CHAR) continue; + + // Read in the version line + strcpy(verbuffer, buffer); + sscanf(verbuffer, "%i %i %i", &new_major, &new_minor, &new_build); + } + fclose(f); + + if(VER(new_major,new_minor,new_build)==0) { + DeleteFile(UPDATED_VERSION_FNAME); + return FALSE; + } + + // Read in the current version values from the registry + cur_major = os_config_read_uint("Version", "Major", 0); + cur_minor = os_config_read_uint("Version", "Minor", 0); + cur_build = os_config_read_uint("Version", "Build", 0); + + // Is the version found in the text file newer than the current version? + if( VER(new_major,new_minor,new_build) <= VER(cur_major,cur_minor,cur_build) ) { + DeleteFile(UPDATED_VERSION_FNAME); + return FALSE; + } + + // Write the new version into the registry + os_config_write_uint("Version", "Major", new_major); + os_config_write_uint("Version", "Minor", new_minor); + os_config_write_uint("Version", "Build", new_build); + + // Get rid of the file + DeleteFile(UPDATED_VERSION_FNAME); + + return TRUE; +} + + +// This function simply returns the interger version value of DirectX +// installed on the user's system +int GetDirectXVersion(void) +{ + LONG lResult; + HKEY hKey = NULL; + + int version_num=0; + if (Dd_dll_handle) { + lResult = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, // Where it is + "Software\\Microsoft\\DirectX", // name of key + NULL, // DWORD reserved + KEY_QUERY_VALUE, // Allows all changes + &hKey // Location to store key + ); + + if (lResult == ERROR_SUCCESS) { + char version[32]; + DWORD dwType, dwLen; + + dwLen = 32; + lResult = RegQueryValueEx( + hKey, // Handle to key + "Version", // The values name + NULL, // DWORD reserved + &dwType, // What kind it is + (ubyte *) version, // value to set + &dwLen // How many bytes to set + ); + + if (lResult == ERROR_SUCCESS) { + CString str; + + version_num = atoi(strstr(version, ".") + 1); + + } else { + int val; + DWORD dwType, dwLen; + + dwLen = 4; + lResult = RegQueryValueEx( + hKey, // Handle to key + "InstalledVersion", // The values name + NULL, // DWORD reserved + &dwType, // What kind it is + (ubyte *) &val, // value to set + &dwLen // How many bytes to set + ); + + if (lResult == ERROR_SUCCESS) { + CString str; + + version_num = val; + + } + } + + RegCloseKey(hKey); + } + } + + return(version_num); +} + + + +typedef int (CALLBACK *LPFN_DIRECTXSETUPGETVERSION)(DWORD *, DWORD *); + +// Attempts to obtain the DirectX version and revision number via the dsetup.dll +bool GetDirectXVersionViaDLL(DWORD *version, DWORD *revision) +{ + HINSTANCE dsetup_dll_handle=NULL; + LPFN_DIRECTXSETUPGETVERSION pfn_DirectXSetupGetVersion=NULL; + + version=0; + revision=0; + + // Check for the DSetup dll, and open it + dsetup_dll_handle=LoadLibrary("dsetup.dll"); + if(dsetup_dll_handle==NULL) { + return FALSE; + } + + // Get the DirectXSetup function + pfn_DirectXSetupGetVersion = (LPFN_DIRECTXSETUPGETVERSION)GetProcAddress(dsetup_dll_handle,"DirectXSetupGetVersionA"); + if(pfn_DirectXSetupGetVersion==NULL) { + FreeLibrary(dsetup_dll_handle); + dsetup_dll_handle=NULL; + return FALSE; + } + + int rc=pfn_DirectXSetupGetVersion(version,revision); + + FreeLibrary(dsetup_dll_handle); + dsetup_dll_handle=NULL; + + if(rc==0) return FALSE; + return TRUE; +} + + +// Converts the given string to lower case +void StringToLower(char *string) +{ + int j; + + for(j=0;string[j]!='\0';j++) + if(isalpha(string[j])) + string[j]=tolower(string[j]); +} + + +// Set the launcher dialog title +void SetLauncherTitleString(void) +{ +#if defined(DEMO) + szTitle.Format(IDS_D3LAUNCH_DEMO_DLGTITLE); +#elif defined(DEMO2) + szTitle.Format(IDS_D3LAUNCH_DEMO2_DLGTITLE); +#elif defined(OEM_GENERIC) + szTitle.Format(IDS_D3LAUNCH_OEM_DLGTITLE); +#elif (defined(OEM_VOODOO3) && !defined(USE_ALL_VIDEO_OPTIONS)) + szTitle.Format(IDS_D3LAUNCH_OEMV3_DLGTITLE); +#elif (defined(OEM_VOODOO3) && defined(USE_ALL_VIDEO_OPTIONS)) + szTitle.Format(IDS_D3LAUNCH_OEM_DLGTITLE); +#elif defined(OEM_AUREAL2) + szTitle.Format(IDS_D3LAUNCH_OEMA2_DLGTITLE); +#elif defined(OEM_KATMAI) + szTitle.Format(IDS_D3LAUNCH_OEMKM_DLGTITLE); +#else + szTitle.Format(IDS_D3LAUNCH_DLGTITLE); +#endif +} + + +// Starts up the online registration program +void Register(bool wait_until_done) +{ + char original_path[MAX_PATH+1]; + char ereg_path[MAX_PATH+1]; + + _getcwd(original_path, MAX_PATH); + strcpy(ereg_path,original_path); + strcat(ereg_path,"\\ereg"); + _chdir(ereg_path); + + // launch the ereg app + STARTUPINFO si; + PROCESS_INFORMATION pi; + + memset( &si, 0, sizeof(STARTUPINFO) ); + si.cb = sizeof(si); + + BOOL ret = CreateProcess( "reg32a.exe", // pointer to name of executable module + NULL, // pointer to command line string + NULL, // pointer to process security attributes + NULL, // pointer to thread security attributes + FALSE, // handle inheritance flag + CREATE_DEFAULT_ERROR_MODE, // creation flags + NULL, // pointer to new environment block + NULL, // pointer to current directory name + &si, // pointer to STARTUPINFO + &pi // pointer to PROCESS_INFORMATION + ); + + // If it was started ok, wait for it to finish before continuing + if(ret && wait_until_done) { + WaitForSingleObject (pi.hProcess, INFINITE); + } + + SetCurrentDirectory(original_path); +} + + +// Copies the appropriate help files into the root directory based +// upon what language is currently selected +void CopyHelpFiles(bool should_overwrite) +{ + char src_hlp_fname[_MAX_PATH+1]; + char src_cnt_fname[_MAX_PATH+1]; + char hlp_filename[_MAX_PATH+1]; + char cnt_filename[_MAX_PATH+1]; + char hlp_ext[_MAX_EXT+1]; + char cnt_ext[_MAX_EXT+1]; + + // Check if files already exist + if(!should_overwrite) { + if(_access(HELP_HLP_FNAME,0x00)!=-1 && _access(HELP_CNT_FNAME,0x00)!=-1) + return; + } + + // Build the source help filenames + _splitpath(HELP_HLP_FNAME,NULL,NULL,hlp_filename,hlp_ext); + _splitpath(HELP_CNT_FNAME,NULL,NULL,cnt_filename,cnt_ext); + + int lang_type=os_config_read_uint(szSectionName,"LanguageType",LANGUAGE_ENGLISH); + switch(lang_type) { + case LANGUAGE_FRENCH: + sprintf(src_hlp_fname,"%s%s%s%s",LANGUAGE_HELP_PATH,hlp_filename,FRENCH_EXT,hlp_ext); + sprintf(src_cnt_fname,"%s%s%s%s",LANGUAGE_HELP_PATH,cnt_filename,FRENCH_EXT,cnt_ext); + break; + case LANGUAGE_GERMAN: + sprintf(src_hlp_fname,"%s%s%s%s",LANGUAGE_HELP_PATH,hlp_filename,GERMAN_EXT,hlp_ext); + sprintf(src_cnt_fname,"%s%s%s%s",LANGUAGE_HELP_PATH,cnt_filename,GERMAN_EXT,cnt_ext); + break; + case LANGUAGE_ITALIAN: + sprintf(src_hlp_fname,"%s%s%s%s",LANGUAGE_HELP_PATH,hlp_filename,ITALIAN_EXT,hlp_ext); + sprintf(src_cnt_fname,"%s%s%s%s",LANGUAGE_HELP_PATH,cnt_filename,ITALIAN_EXT,cnt_ext); + break; + case LANGUAGE_SPANISH: + sprintf(src_hlp_fname,"%s%s%s%s",LANGUAGE_HELP_PATH,hlp_filename,SPANISH_EXT,hlp_ext); + sprintf(src_cnt_fname,"%s%s%s%s",LANGUAGE_HELP_PATH,cnt_filename,SPANISH_EXT,cnt_ext); + break; + default: + sprintf(src_hlp_fname,"%s%s%s",LANGUAGE_HELP_PATH,hlp_filename,hlp_ext); + sprintf(src_cnt_fname,"%s%s%s",LANGUAGE_HELP_PATH,cnt_filename,cnt_ext); + break; + } + + // If any of the source files don't exist, get outta here + if(_access(src_hlp_fname,0x00)==-1 || _access(src_cnt_fname,0x00)==-1) { + // Try the english files instead + sprintf(src_hlp_fname,"%s%s%s",LANGUAGE_HELP_PATH,hlp_filename,hlp_ext); + sprintf(src_cnt_fname,"%s%s%s",LANGUAGE_HELP_PATH,cnt_filename,cnt_ext); + if(_access(src_hlp_fname,0x00)==-1 || _access(src_cnt_fname,0x00)==-1) + return; + } + + // Delete current help files (and their created files) + DeleteFile(HELP_HLP_FNAME); + DeleteFile(HELP_CNT_FNAME); + DeleteFile(HELP_GID_FNAME); + DeleteFile(HELP_FTS_FNAME); + + // Copy over the correct files + CopyFile(src_hlp_fname,HELP_HLP_FNAME,FALSE); + CopyFile(src_cnt_fname,HELP_CNT_FNAME,FALSE); +} + + +// Returns true if this machine can support the CPUID instruction +bool SupportsCPUID () +{ + bool enabled=true; + + __try{ + + _asm{ + pushad + __emit 0x0f //CPUID + __emit 0xa2 //CPUID + popad + } + } + __except(1) + { + enabled=false; + } + + return enabled; +} + +// Returns true if this machine can support katmai instructions +bool SupportsKatmai () +{ + int result=0; + + + if(SupportsCPUID()) + { + _asm + { + pushad + xor eax,eax; + inc eax; + __emit 0x0f //CPUID + __emit 0xa2 //CPUID + + and edx,0x02000000; + je THE_END; + + inc result; + + THE_END: + popad + } + + if(!result) + return 0; + } + else + return 0; + + return 1; +} + + +// Removes any whitespace padding from the end of a string +void RemoveTrailingWhitespace(char *s) +{ + int last_char_pos; + + last_char_pos=strlen(s)-1; + while(last_char_pos>=0 && isspace(s[last_char_pos])) { + s[last_char_pos]='\0'; + last_char_pos--; + } +} + +// Returns a pointer to the first non-whitespace char in given string +char *SkipInitialWhitespace(char *s) +{ + while((*s)!='\0' && isspace(*s)) + s++; + + return(s); +} + +// Parses the launcher config file and sets appropriate values +void ReadConfigFile(void) +{ + char path[_MAX_PATH+1]; + char filebuffer[4096+1]; + char *line, *parm; + FILE *f; + bool done; + + // Setup Config Defaults + LanguageSelectionEnabled=TRUE; + EregEnabled=FALSE; + + // Try and open the config file + sprintf(path,"%s%s",LANGUAGE_LAUNCHER_PATH,LAUNCHER_CONFIG_FNAME); + f = fopen(path, "rt"); + if(f == NULL) return; + + // Read in config file + done=FALSE; + while (!done && !feof(f)) { + + strcpy(filebuffer,""); + fgets(filebuffer, 4096, f); + + // Get rid of whitespace padding + RemoveTrailingWhitespace(filebuffer); + line=SkipInitialWhitespace(filebuffer); + + // If it's an empty line or a comment, skip it + if(strlen(line)==0 || strncmp(line,"//",2)==0) + continue; + + // split off line's parameter + line=strtok(line,"="); + if(line==NULL) continue; + parm=strtok(NULL,""); + if(parm==NULL) continue; + + RemoveTrailingWhitespace(line); + parm=SkipInitialWhitespace(parm); + + // Process config file directives + if(stricmp(line,"LANGUAGE_SELECTION")==0) { + if(stricmp(parm,"ON")==0) { + LanguageSelectionEnabled=TRUE; + } + else { + LanguageSelectionEnabled=FALSE; + } + } + else if(stricmp(line,"EREG")==0) { + if(stricmp(parm,"ON")==0) { + EregEnabled=TRUE; + } + else { + EregEnabled=FALSE; + } + } + } + fclose(f); +} + + +// Constructs a path in the local file system's syntax +// newPath: stores the constructed path +// absolutePathHeader: absolute path on which the sub directories will be appended +// (specified in local file system syntax) +// takes a variable number of subdirectories which will be concatenated on to the path +// the last argument in the list of sub dirs *MUST* be NULL to terminate the list +void ddio_MakePath(char* newPath, const char* absolutePathHeader, const char* subDir, ...) +{ + const char delimiter = '\\'; + va_list args; + char* currentDir = NULL; + int pathLength = 0; + + assert(newPath); + assert(absolutePathHeader); + assert(subDir); + + if (newPath != absolutePathHeader) + { + strcpy(newPath, absolutePathHeader); + } + + // Add the first sub directory + pathLength = strlen(newPath); + if (newPath[pathLength - 1] != delimiter) + { + newPath[pathLength] = delimiter; // add the delimiter + newPath[pathLength+1] = 0; // terminate the string + } + strcat(newPath, subDir); + + // Add the additional subdirectories + va_start(args, subDir); + while ((currentDir = va_arg(args, char*)) != NULL) + { + pathLength = strlen(newPath); + if (newPath[pathLength - 1] != delimiter) + { + newPath[pathLength] = delimiter; // add the delimiter + newPath[pathLength+1] = 0; // terminate the string + } + strcat(newPath, currentDir); + } + va_end(args); +} + + +// Split a pathname into its component parts +void ddio_SplitPath(const char* srcPath, char* path, char* filename, char* ext) +{ + char drivename[_MAX_DRIVE], dirname[_MAX_DIR]; + + _splitpath(srcPath, drivename, dirname, filename, ext); + + if (path) + sprintf(path, "%s%s", drivename, dirname); +} + diff --git a/D3Launch/D3Launch.h b/D3Launch/D3Launch.h new file mode 100644 index 00000000..f0309ece --- /dev/null +++ b/D3Launch/D3Launch.h @@ -0,0 +1,289 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/D3Launch.h $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 40 6/18/99 4:42p Nate + * Added non-LaserLock ROW version + * + * 39 6/17/99 1:57p Nate + * Enabled italian for ROW builds + * + * 38 6/09/99 2:46p Nate + * Minor changes for different builds + * + * 37 5/21/99 3:38p Nate + * Added changes for Rest of World release (new update directory path) + * + * 36 5/20/99 12:53p Nate + * Added GLSetup window, EAX mixer support, and CHFlight+Mouseman Mode + * options + * + * 35 5/19/99 12:29p Nate + * Fixed openGL crash, changed Network speed default, changed OpenGL + * detection to default to unchecked, and removed config file parsing from + * US version + * + * 34 5/07/99 11:23a Nate + * Added support for a launcher config file + * + * 33 5/05/99 11:38p Nate + * Disabled Language selection for US release builds + * + * 32 5/02/99 12:38p Nate + * Disabled GLSetup for final release + * + * 31 4/27/99 10:42p Nate + * Added vsync enabling when direct3d is chosen + * + * 30 4/15/99 12:03p Nate + * Added "Descent 3 Demo 2" build type + * + * 29 4/08/99 1:13p Nate + * Added Pentium III detection + * + * 28 3/29/99 3:14p Nate + * Added OEM_GENERIC + * + * 27 3/19/99 10:18a Nate + * Added OEM_GENERIC compile type + * + * 26 3/12/99 3:29p Nate + * Added more multi-language support + * + * 25 3/02/99 5:45p Nate + * Lots of little changes/fixes + * + * 24 2/26/99 12:50p Nate + * Changed OEM_Voodoo3 names + * + * 23 2/24/99 8:37p Nate + * Various little dialog changes, added "Install Drivers" dialog + * + * 22 2/24/99 1:46p Nate + * Added multi-language support + * + * 21 2/17/99 2:23p Nate + * Added some OEM changes + * + * 20 2/05/99 3:51p Nate + * Added conditional compilation directives for OEM support + * + * 19 11/30/98 3:00p Nate + * Added StringToLower() + * + * 18 10/15/98 7:30p Nate + * + * 17 10/15/98 11:31a Nate + * Added Launcher Sound toggling + * + * 16 10/08/98 6:23p Nate + * Fixed a few bugs. + * + * 15 10/02/98 7:09p Nate + * + * 14 9/30/98 1:59p Nate + * Added Version constants for demo and full builds + * + * 13 9/29/98 6:05p Nate + * Added the functionality to update the game version from a text file. + * + * 12 9/22/98 3:33p Nate + * Added conditional compiling to help system (can toggle between HTML and + * standard windows help) + * + * 11 9/21/98 6:06p Nate + * + * 10 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 9 9/16/98 3:23p Nate + * Added m_straight_to_setup detection + * + * 8 9/03/98 6:57p Nate + * Fixed StretchBlt() problem by doing some 256 color conversions + * + * 7 9/02/98 6:42p Nate + * Added improved sound support. + * + * 6 9/01/98 7:15p Nate + * Major Revision #2 + * + * 5 8/31/98 6:44p Nate + * Major Revision + * + * 4 8/24/98 7:06p Nate + * Added new AutoUpdate features, and fixed display glitches + * + * 3 8/10/98 10:44a Nate + * Added Language selection support + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +// D3Launch.h : main header file for the D3LAUNCH application +// + +#if !defined(AFX_D3LAUNCH_H__9149CF38_207D_11D2_8CBD_00A0C96ED60D__INCLUDED_) +#define AFX_D3LAUNCH_H__9149CF38_207D_11D2_8CBD_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +/****************************** +** The Launcher Version ID's ** +******************************/ +#define LAUNCHER_VERSION_ID 1.0 +#define LAUNCHER_DEMO_VERSION_ID 1.0 + +// Uncomment this if you want to use the HTML help system for the launcher +//#define USE_HTML_HELP_SYSTEM + +// Uncomment one of the following if you want to do a special build +//#define DEMO +//#define DEMO2 +//#define OEM_GENERIC +//#define OEM_VOODOO3 +//#define OEM_AUREAL2 +//#define OEM_KATMAI +//#define FULL_US_RELEASE +#define FULL_ROW_RELEASE +//#define FULL_AUSSIE_RELEASE + +// Uncomment this if you are doing an initial UK version build +//#define INITIAL_UK_RELEASE + +// Uncomment this if you are doing a non-LaserLock version (full ROW variation) +//#define ROW_NLL_RELEASE + +// Uncomment this is you are doing an OEM_VOODOO3 build but want it to support all API's +//#define USE_ALL_VIDEO_OPTIONS + +// Uncomment this if you want multi-language support +#define USE_MULTI_LANGUAGES + +// Uncomment this if you want Italian to be a selectable language +#define ENABLE_ITALIAN + +// Uncomment this if you want GLSetup to be a non-selectable option +//#define DISABLE_GLSETUP + +// Macro for computing a "comparable" version ID +#define VER(major, minor, build) (100*100*major+100*minor+build) + +// Comment char to be used in version files +#define VERSION_FILE_COMMENT_CHAR ';' + +#include "resource.h" // main symbols + +// Help Files +#define MAIN_MENU_HELP "D3L_hlp1.htm" +#define UPDATE_HELP "D3L_hlp2.htm" +#define DIRECTXTAB_HELP "D3L_hlp3.htm" +#define VIDEOTAB_HELP "D3L_hlp4.htm" +#define AUDIOTAB_HELP "D3L_hlp5.htm" +#define JOYSTICKTAB_HELP "D3L_hlp6.htm" +#define SPEEDTAB_HELP "D3L_hlp7.htm" +#define NETWORKTAB_HELP "D3L_hlp8.htm" +#define KEYBOARDTAB_HELP "D3L_hlp9.htm" + +///////////////////////////////////////////////////////////////////////////// +// CD3LaunchApp: +// See D3Launch.cpp for the implementation of this class +// + +class CD3LaunchApp : public CWinApp +{ +public: + CD3LaunchApp(); + + HINSTANCE m_hResInst; + HINSTANCE m_hDefResInst; + + CBitmap m_bkBmap; + CPalette m_palette; + + CBitmap m_bkBmapBig; + int m_straight_to_update; // NOTE : this is for going right to the autoupdate feature from the PXO screen + // it should only ever be set from the command line parser + + int m_straight_to_setup; // NOTE : this is for going straight to the setup if this is + // the first time (after D3 is installed) that the + // launcher has been run + + BOOL FirstInstance(); + + // parse for special (outrage) command-line arguments + void OutrageParseCommandLine(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CD3LaunchApp) + public: + virtual BOOL InitInstance(); + virtual int ExitInstance(); + //}}AFX_VIRTUAL + +// Implementation + + //{{AFX_MSG(CD3LaunchApp) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +extern CD3LaunchApp theApp; + +void help_launch(char *help_filename); +void url_launch(char *url); +BOOL PlayResource(LPSTR lpName, bool WaitUntilDone); +BOOL GetBitmapAndPalette(UINT nIDResource, CBitmap *bitmap, CPalette *pal); +BOOL GetBitmapAndPalette(LPCTSTR lpszResourceName, CBitmap *bitmap, CPalette *pal); +void DeferMessages(void); +int GetDirectXVersion(void); +bool GetDirectXVersionViaDLL(DWORD *version, DWORD *revision); +void StringToLower(char *string); +void SetLauncherTitleString(void); +void Register(bool wait_until_done); +void CopyHelpFiles(bool should_overwrite); +void ReadConfigFile(void); + +bool SupportsCPUID(); +bool SupportsKatmai(); + +extern bool LanguageSelectionEnabled; +extern bool EregEnabled; + +extern int LauncherSoundEnabled; +extern bool VideoCardsDetected; +extern bool DetailLevelConfigured; +extern bool NewLanguageSelected; +extern bool RenderersDetected; +extern bool GlideInited; +extern int Dx_version; +extern HINSTANCE Dd_dll_handle; +extern HINSTANCE opengl_dll_handle; + +extern double DlgWidthModifier; +extern double DlgHeightModifier; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_D3LAUNCH_H__9149CF38_207D_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/D3Launch.rc b/D3Launch/D3Launch.rc new file mode 100644 index 00000000..01d64e3b --- /dev/null +++ b/D3Launch/D3Launch.rc @@ -0,0 +1,990 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif\r\n" + "#include ""res\\D3Launch.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON DISCARDABLE "res\\D3Launch.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_D3LAUNCH_DIALOG DIALOGEX 0, 0, 373, 258 +STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + CONTROL "PLAY",IDC_BTN_PLAY,"Button",BS_OWNERDRAW | BS_BITMAP | + WS_TABSTOP,35,63,85,14 + CONTROL "SETUP",IDC_BTN_SETUP,"Button",BS_OWNERDRAW | BS_BITMAP | + WS_TABSTOP,35,94,85,15 + CONTROL "UPDATE",IDC_BTN_UPDATE,"Button",BS_OWNERDRAW | + BS_BITMAP | WS_TABSTOP,35,125,86,14 + CONTROL "OUTRAGE",IDC_BTN_WEBPAGE,"Button",BS_OWNERDRAW | + BS_BITMAP | WS_TABSTOP,42,161,85,15 + CONTROL "README",IDC_BTN_README,"Button",BS_OWNERDRAW | + BS_BITMAP | WS_TABSTOP,224,63,85,15 + CONTROL "DIRECTX",IDC_BTN_DIRECTX,"Button",BS_OWNERDRAW | + BS_BITMAP | WS_TABSTOP,224,94,87,14 + CONTROL "UNINSTALL",IDC_BTN_UNINSTALL,"Button",BS_OWNERDRAW | + BS_BITMAP | WS_TABSTOP,224,125,86,14 + CONTROL "PXO",IDC_BTN_PXO,"Button",BS_OWNERDRAW | BS_BITMAP | + WS_TABSTOP,214,161,86,14 + CONTROL "HELP",ID_HELP,"Button",BS_OWNERDRAW | BS_BITMAP | + WS_TABSTOP,167,188,27,14 + CONTROL "QUIT",IDC_BTN_QUIT,"Button",BS_OWNERDRAW | BS_BITMAP | + WS_TABSTOP,273,237,55,8 + CONTROL "LIGHT",IDC_BTN_LIGHT,"Button",BS_OWNERDRAW | BS_BITMAP | + WS_DISABLED,263,3,50,14 + CONTROL "ANIM",IDC_ANIM_BUTTON,"Button",BS_OWNERDRAW | BS_BITMAP | + WS_DISABLED,164,91,24,14 +END + +IDD_UPDATE_DIALOG DIALOGEX 0, 0, 312, 253 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Descent 3 Auto-Update" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDYES,157,232,48,14 + PUSHBUTTON "Cancel",IDCANCEL,207,232,48,14 + PUSHBUTTON "Help",ID_HELP,257,232,48,14 + CONTROL "Progress1",IDC_PROGRESS1,"msctls_progress32",WS_BORDER, + 42,66,263,14 + RTEXT "Progress:",IDC_STATIC,5,68,31,8 + LISTBOX IDC_LIST1,7,85,298,125,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | + WS_HSCROLL + CTEXT "A new version of Descent 3 is available! Would you like to download it?", + IDC_USERMSG,7,216,298,12,0,WS_EX_TRANSPARENT + LTEXT "Status:",IDC_STATIC,7,236,23,8 + LTEXT "Waiting...",IDC_STATUSBAR,34,236,113,8 + EDITTEXT IDC_MOTD_EDIT,7,14,234,45,ES_MULTILINE | ES_READONLY | + ES_WANTRETURN | WS_VSCROLL | NOT WS_TABSTOP + LTEXT "Message of the Day:",IDC_STATIC,7,3,66,8 + EDITTEXT IDC_YOUR_VERSION_EDIT,252,15,53,14,ES_CENTER | + ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + EDITTEXT IDC_LATEST_VERSION_EDIT,252,45,53,14,ES_CENTER | + ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + LTEXT "Latest Version:",IDC_STATIC,253,33,48,8 + LTEXT "Your Version:",IDC_STATIC,253,3,43,8 +END + +IDD_PROPPAGE_JOYSTICK DIALOG DISCARDABLE 0, 0, 221, 159 +STYLE WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Controls" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Enable Force Feedback (for current joystick)", + IDC_FF_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14, + 48,189,10 + PUSHBUTTON "Joystick Calibration / Settings",IDC_BTN_CALIBRATE,7, + 120,207,15 + PUSHBUTTON "Redetect Current Joystick",IDC_BTN_DETECT,7,137,207,15 + EDITTEXT IDC_PRIMARY_JOYSTICK_TEXT,7,17,207,13,ES_AUTOHSCROLL | + ES_READONLY + LTEXT "Current Joystick:",IDC_STATIC,7,7,53,8 + COMBOBOX IDC_JOYSTICK_LIST,186,7,28,90,CBS_DROPDOWNLIST | + CBS_SORT | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Controller Options",IDC_STATIC,7,36,207,49 + LTEXT "NOTE:",IDC_STATIC,7,90,23,8 + LTEXT "If you wish to view or change the settings for the joysticks on your system, click on the Joystick Calibration/Settings button below.", + IDC_STATIC,34,89,180,28 + CONTROL "Enable CH Flightstick Pro Mode (only if you have one)", + IDC_CHFLIGHT_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 14,59,189,10 + CONTROL "Enable Logitech Mouseman Mode (only if you have one)", + IDC_MOUSEMAN_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 14,71,189,10 +END + +IDD_PROPPAGE_VIDEO DIALOG DISCARDABLE 0, 0, 221, 159 +STYLE WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Video" +FONT 8, "MS Sans Serif" +BEGIN + COMBOBOX IDC_VIDEOCARD_LIST,6,17,208,79,CBS_DROPDOWNLIST | + CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Redetect Available Rendering Devices", + IDC_VIDEOCARD_DETECT,6,108,208,15 + LTEXT "Currently Selected Rendering Device:",IDC_STATIC,6,7, + 120,8 + LTEXT "NOTE:",IDC_STATIC,6,39,23,8 + LTEXT "A 3D Accelerated Rendering Device must be selected in order for Descent 3 to run. Select your desired renderer from the above drop-down list.", + IDC_STATIC,34,39,180,31 + LTEXT "If your video card supports 3Dfx Glide, we strongly recommend that you choose it as your Rendering Device.", + IDC_STATIC,34,72,180,27 +END + +IDD_PROPPAGE_AUDIO DIALOG DISCARDABLE 0, 0, 221, 159 +STYLE WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Audio" +FONT 8, "MS Sans Serif" +BEGIN + COMBOBOX IDC_AUDIO_LIST,7,17,207,90,CBS_DROPDOWNLIST | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + CONTROL "Software",IDC_MIXER_SOFTWARE,"Button", + BS_AUTORADIOBUTTON | WS_GROUP,16,49,113,10 + CONTROL "DirectSound",IDC_MIXER_DS8BIT,"Button", + BS_AUTORADIOBUTTON,16,62,55,10 + CONTROL "DirectSound 3D",IDC_MIXER_DS3D,"Button", + BS_AUTORADIOBUTTON,16,75,91,10 + CONTROL "Aureal 3D Sound",IDC_MIXER_AUREAL,"Button", + BS_AUTORADIOBUTTON,16,88,102,10 + CONTROL "Creative EAX",IDC_MIXER_EAX,"Button",BS_AUTORADIOBUTTON, + 16,101,58,10 + CONTROL "Enable Sound in the D3 Launcher",IDC_LAUNCHER_SND_CHECK, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,122,131,10 + PUSHBUTTON "Redetect All Available Sound Devices", + IDC_BTN_AUDIO_DETECT,7,138,207,14 + LTEXT "Currently Selected Sound Device:",IDC_STATIC,7,7,108,8 + CONTROL "DirectSound (16 Bit)",IDC_MIXER_DS16BIT,"Button", + BS_AUTORADIOBUTTON | NOT WS_VISIBLE,135,121,79,10 + LTEXT "NOTE:",IDC_STATIC,146,40,23,8 + LTEXT "Select the sound device you wish to use from the pull-down box above, and then select an available mixer from the list to the left.", + IDC_STATIC,146,51,68,56 + GROUPBOX "Available Mixers for Device",IDC_STATIC,7,36,130,80 +END + +IDD_PROPPAGE_SPEED DIALOG DISCARDABLE 0, 0, 221, 159 +STYLE WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Speed" +FONT 8, "MS Sans Serif" +BEGIN + COMBOBOX IDC_SPEED_LIST,7,17,207,95,CBS_DROPDOWNLIST | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Detect System Properties",IDC_BTN_SPEED_DETECT,7,138, + 207,14 + LTEXT "Default Detail Level",IDC_STATIC,7,7,63,8 + LTEXT "CPU Type:",IDC_STATIC,15,50,80,8 + LTEXT "CPU Speed:",IDC_STATIC,15,60,80,8 + LTEXT "Total RAM:",IDC_STATIC,15,70,80,8 + LTEXT "VRAM Transfer Rate:",IDC_STATIC,15,90,80,8 + LTEXT "3D Graphics Accelerator*:",IDC_STATIC,15,100,85,8 + LTEXT "",IDC_CPU_TYPE,105,50,85,8 + LTEXT "",IDC_CPU_SPEED,105,60,85,8 + LTEXT "",IDC_TOTAL_RAM,105,70,85,8 + LTEXT "RAM Transfer Rate:",IDC_STATIC,15,80,80,8 + LTEXT "",IDC_RAM_SPEED,105,80,85,8 + LTEXT "",IDC_VRAM_SPEED,105,90,85,8 + LTEXT "",IDC_3D_GRAPHICS_ACCELERATOR,105,100,85,8 + GROUPBOX "System Properties",IDC_STATIC,7,37,207,78 + LTEXT "* Configured in the ""Video"" tab.",IDC_STATIC,7,121, + 207,8 +END + +IDD_PROPPAGE_NETWORK DIALOG DISCARDABLE 0, 0, 221, 159 +STYLE WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Network" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "None",IDC_NONE,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 14,19,33,10 + CONTROL "Dialup Networking",IDC_DIALUP,"Button", + BS_AUTORADIOBUTTON,14,29,74,10 + CONTROL "LAN/Direct Connection (and AOL)",IDC_LAN,"Button", + BS_AUTORADIOBUTTON,14,39,142,10 + CONTROL "28.8K Modem",IDC_28K_CONNECTION,"Button", + BS_AUTORADIOBUTTON | WS_GROUP,14,67,60,10 + CONTROL "33.6K Modem",IDC_33K_CONNECTION,"Button", + BS_AUTORADIOBUTTON,14,78,106,10 + CONTROL "56K Modem",IDC_56K_CONNECTION,"Button", + BS_AUTORADIOBUTTON,14,89,155,10 + CONTROL "Single Channel ISDN",IDC_SINGLE_ISDN_CONNECTION,"Button", + BS_AUTORADIOBUTTON,14,100,83,10 + CONTROL "Dual Channel ISDN, Cable Modems",IDC_CABLE_CONNECTION, + "Button",BS_AUTORADIOBUTTON,14,111,155,10 + CONTROL "T1, ADSL, T3, etc.",IDC_FAST_CONNECTION,"Button", + BS_AUTORADIOBUTTON,14,122,95,10 + GROUPBOX "Internet Connection",IDC_CONNECT_TYPE_GROUP,7,7,207,46 + GROUPBOX "Connection Speed",IDC_CONNECT_SPEED_GROUP,7,57,207,77 + LTEXT "NOTE: Inaccurate settings will hinder game performance! ", + IDC_STATIC,7,141,207,11 +END + +IDD_WAIT_DIALOG DIALOG DISCARDABLE 0, 0, 122, 31 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION +CAPTION "Please Wait" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Checking system properties...",IDC_STATIC,15,10,95,10 +END + +IDD_PROPPAGE_KEYBOARD DIALOG DISCARDABLE 0, 0, 221, 159 +STYLE WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Misc." +FONT 8, "MS Sans Serif" +BEGIN + COMBOBOX IDC_LANGUAGE_COMBO,15,18,189,84,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + CONTROL "United States (Standard)",IDC_US_KEYBOARD,"Button", + BS_AUTORADIOBUTTON | WS_GROUP,15,52,93,10 + CONTROL "French",IDC_FRENCH_KEYBOARD,"Button",BS_AUTORADIOBUTTON, + 15,62,38,10 + CONTROL "German",IDC_GERMAN_KEYBOARD,"Button",BS_AUTORADIOBUTTON, + 15,72,142,10 + EDITTEXT IDC_COMMANDLINE_EDIT,15,131,189,14,ES_AUTOHSCROLL + GROUPBOX "Keyboard Type",IDC_STATIC,7,42,207,43 + GROUPBOX "Optional D3 Command-line Switches",IDC_STATIC,7,121,207, + 31 + GROUPBOX "Language",IDC_STATIC,7,7,207,31 + GROUPBOX "Performance Options",IDC_STATIC,7,88,207,29 + CONTROL "Always disable FindFast when running Descent 3", + IDC_FINDFAST_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 15,100,189,10 +END + +IDD_MESSAGE_WINDOW DIALOGEX 0, 0, 129, 69 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_CLIENTEDGE +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + CTEXT "",IDC_WND_MSG_MAIN,10,6,110,16 + CTEXT "",IDC_WND_MSG_STATUS,10,31,110,8 + PUSHBUTTON "Cancel",IDC_BTN_CANCEL,40,48,50,14 +END + +IDD_SITE_SELECTION_DIALOG DIALOGEX 0, 0, 324, 138 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Patch Download Site Selection" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + CONTROL "List1",IDC_SITE_LIST,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SHOWSELALWAYS | WS_BORDER | + WS_TABSTOP,6,16,311,95,WS_EX_CLIENTEDGE + PUSHBUTTON "Begin Download",IDOK,59,117,94,14 + PUSHBUTTON "Cancel",IDCANCEL,170,117,98,14 + LTEXT "Select the site you wish to download from:",IDC_STATIC, + 6,4,247,8 +END + +IDD_MOTD_DIALOG DIALOG DISCARDABLE 0, 0, 261, 117 +STYLE DS_MODALFRAME | DS_CENTER | WS_CAPTION | WS_SYSMENU +CAPTION "Descent 3 Message of the Day" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Close",IDOK,87,98,87,14 + LISTBOX IDC_LIST1,6,6,249,85,NOT LBS_NOTIFY | + LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_VSCROLL | + WS_HSCROLL | WS_TABSTOP +END + +IDD_PROPPAGE_DIRECTX DIALOG DISCARDABLE 0, 0, 221, 159 +STYLE WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "DirectX" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "Visit Microsoft's DirectX Download Page",IDC_GET_DX,7, + 138,207,14 + LTEXT "Your DirectX Version:",IDC_STATIC,17,21,69,12, + SS_CENTERIMAGE + CTEXT "Unknown or Not Installed",IDC_DX_VERSION,91,21,111,12, + SS_CENTERIMAGE | SS_SUNKEN + LTEXT "NOTE:",IDC_STATIC,7,68,23,8 + LTEXT "Descent 3 requires DirectX 3.0 (or greater). DirectX 6.0 is required for Direct3D, Force Feedback, Direct Play, and Direct Sound 3D. You can install DirectX 6.1 from the Descent 3 CD by clicking the ""Install Drivers"" button on the main launcher window.", + IDC_STATIC,34,68,180,42 + GROUPBOX "DirectX Version Information",IDC_STATIC,7,7,207,54 + CTEXT "Needs Updating (see below)",IDC_DX_STATUS,91,38,111,12, + SS_CENTERIMAGE | SS_SUNKEN + LTEXT "Your Version Status:",IDC_STATIC,17,38,69,12, + SS_CENTERIMAGE + LTEXT "You can also download DirectX 6.1 from Microsoft's DirectX Web Page (the button below will take you there).", + IDC_STATIC,34,114,180,18 +END + +IDD_MSG_DLG DIALOGEX 0, 0, 111, 37 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_CLIENTEDGE +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + CTEXT "Scanning System Devices",IDC_SCANNING_TEXT,7,7,97,8 + CTEXT "Please Wait...",IDC_WAIT_TEXT,7,22,97,8 +END + +IDD_VIDEODETECT_DLG DIALOGEX 0, 0, 189, 116 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION +EXSTYLE WS_EX_CLIENTEDGE +CAPTION "Video Device Detection" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "Scan for the Selected Video Devices",IDOK,7,95,175,14 + CONTROL "Direct3D",IDC_DIRECT3D_CHECK,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,18,19,44,10 + CONTROL "3Dfx Glide",IDC_GLIDE_CHECK,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,18,32,49,10 + CONTROL "OpenGL",IDC_OPENGL_CHECK,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,18,45,43,10 + LTEXT "Select the video devices to detect on your system:", + IDC_STATIC,7,7,175,10 + LTEXT "NOTE:",IDC_STATIC,7,64,23,8 + LTEXT "If you experience any problems while scanning, refer to the Troubleshooting section of the ReadMe file for help.", + IDC_STATIC,36,63,146,26 +END + +IDD_DRIVERS_DIALOG DIALOG DISCARDABLE 0, 0, 199, 114 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Driver Installation Menu" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Return to Launcher",IDOK,7,92,131,15 + PUSHBUTTON "Help",ID_HELP,142,92,50,15 + PUSHBUTTON "Install Microsoft DirectX 6.1",IDC_DIRECTX_BUTTON,14,20, + 171,21,BS_FLAT + PUSHBUTTON "Install OpenGL drivers with GLSetup Beta", + IDC_GLSETUP_BUTTON,14,44,171,21,BS_FLAT + GROUPBOX "Options",IDC_STATIC,7,7,185,67 +END + +IDD_GLSETUP_DIALOG DIALOGEX 0, 0, 209, 179 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CLIENTEDGE +CAPTION "GLSetup Beta" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDCANCEL,7,154,195,18 + PUSHBUTTON "Install using Public Beta v0.99",IDC_INSTALL_BUTTON,7, + 114,195,18 + PUSHBUTTON "Visit the GLSetup Web Site",IDC_VISIT_BUTTON,7,134,195, + 18 + LTEXT "Before installing OpenGL drivers you should have DirectX 6.0 or higher installed on your machine. If you do not have DirectX 6.0 installed, exit now and install it.", + IDC_INFO_STATIC,7,7,195,31 + LTEXT "This version of GLSetup (v0.99) is a public beta. You should check the GLSetup web site (http://www.glsetup.com) to see if the release version is available before installing.", + IDC_INFO2_STATIC,7,42,195,31 + LTEXT "Please see the GLSetup readme (in the README.TXT in the /GLSetup directory of Descent 3 CD 1) for information on reporting a problem with GLSetup.", + IDC_INFO3_STATIC,7,78,195,29 +END + +IDD_FINDFASTDLG DIALOG DISCARDABLE 0, 0, 214, 146 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION +CAPTION "FindFast Detected" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Yes",IDOK,50,125,50,14 + PUSHBUTTON "No",IDCANCEL,112,125,50,14 + CONTROL "Always disable FindFast when running Descent 3", + IDC_FINDFASTCHKBOX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 7,103,170,10 + LTEXT "We have determined that your computer is running FindFast. This program can have a negative effect on the performance of Descent 3 and we STRONGLY recommend that you not run FindFast while playing Descent 3. ", + IDC_STATIC,7,7,200,35 + LTEXT "If you terminate FindFast, it may take your computer slightly longer to to open files, but everything else will work normally. FindFast will be reenabled the next time you restart your computer.\n\nWould you like to terminate FindFast?", + IDC_STATIC,7,45,200,50 +END + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "D3Launch MFC Application\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "D3Launch\0" + VALUE "LegalCopyright", "Copyright (C) 1998\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "D3Launch.EXE\0" + VALUE "ProductName", "D3Launch Application\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_D3LAUNCH_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 366 + TOPMARGIN, 7 + BOTTOMMARGIN, 251 + END + + IDD_UPDATE_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 305 + TOPMARGIN, 7 + BOTTOMMARGIN, 246 + END + + IDD_PROPPAGE_JOYSTICK, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 214 + TOPMARGIN, 7 + BOTTOMMARGIN, 152 + END + + IDD_PROPPAGE_VIDEO, DIALOG + BEGIN + LEFTMARGIN, 6 + RIGHTMARGIN, 214 + TOPMARGIN, 7 + BOTTOMMARGIN, 152 + END + + IDD_PROPPAGE_AUDIO, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 214 + TOPMARGIN, 7 + BOTTOMMARGIN, 152 + END + + IDD_PROPPAGE_SPEED, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 214 + TOPMARGIN, 7 + BOTTOMMARGIN, 152 + END + + IDD_PROPPAGE_NETWORK, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 214 + TOPMARGIN, 7 + BOTTOMMARGIN, 152 + END + + IDD_WAIT_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 115 + TOPMARGIN, 7 + BOTTOMMARGIN, 24 + END + + IDD_PROPPAGE_KEYBOARD, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 214 + TOPMARGIN, 7 + BOTTOMMARGIN, 152 + END + + IDD_MESSAGE_WINDOW, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 122 + TOPMARGIN, 7 + BOTTOMMARGIN, 62 + END + + IDD_SITE_SELECTION_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 317 + TOPMARGIN, 7 + BOTTOMMARGIN, 131 + END + + IDD_MOTD_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 254 + TOPMARGIN, 7 + BOTTOMMARGIN, 110 + END + + IDD_PROPPAGE_DIRECTX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 214 + TOPMARGIN, 7 + BOTTOMMARGIN, 152 + END + + IDD_MSG_DLG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 104 + TOPMARGIN, 7 + BOTTOMMARGIN, 30 + END + + IDD_VIDEODETECT_DLG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 182 + TOPMARGIN, 7 + BOTTOMMARGIN, 109 + END + + IDD_DRIVERS_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 192 + TOPMARGIN, 7 + BOTTOMMARGIN, 107 + END + + IDD_GLSETUP_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 202 + TOPMARGIN, 7 + BOTTOMMARGIN, 172 + END + + IDD_FINDFASTDLG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 207 + TOPMARGIN, 7 + BOTTOMMARGIN, 139 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_D3LAUNCH_BG BITMAP DISCARDABLE "res\\bitmap1.bmp" +PLAYU BITMAP DISCARDABLE "res\\Play.bmp" +PLAYD BITMAP DISCARDABLE "res\\PlayD.bmp" +PLAYM BITMAP DISCARDABLE "res\\PlayM.bmp" +QUITU BITMAP DISCARDABLE "res\\QuitU.bmp" +QUITD BITMAP DISCARDABLE "res\\QuitD.bmp" +QUITM BITMAP DISCARDABLE "res\\QuitM.bmp" +LIGHTU BITMAP DISCARDABLE "res\\LightU.BMP" +LIGHTM BITMAP DISCARDABLE "res\\LightM.BMP" +LIGHTD BITMAP DISCARDABLE "res\\LightD.BMP" +OUTRAGED BITMAP DISCARDABLE "res\\OutrageD.BMP" +OUTRAGEM BITMAP DISCARDABLE "res\\OutrageM.BMP" +OUTRAGEU BITMAP DISCARDABLE "res\\OutrageU.BMP" +PXOD BITMAP DISCARDABLE "res\\Pxod.bmp" +PXOM BITMAP DISCARDABLE "res\\Pxom.bmp" +PXOU BITMAP DISCARDABLE "res\\Pxou.bmp" +PLAYX BITMAP DISCARDABLE "res\\PlayX.BMP" +READMED BITMAP DISCARDABLE "res\\ReadMeD.BMP" +READMEM BITMAP DISCARDABLE "res\\ReadMeM.BMP" +READMEU BITMAP DISCARDABLE "res\\ReadMeU.BMP" +READMEX BITMAP DISCARDABLE "res\\ReadMeX.BMP" +SETUPD BITMAP DISCARDABLE "res\\SetupD.bmp" +SETUPM BITMAP DISCARDABLE "res\\SetupM.bmp" +SETUPU BITMAP DISCARDABLE "res\\SetupU.bmp" +SETUPX BITMAP DISCARDABLE "res\\SetupX.bmp" +UPDATEM BITMAP DISCARDABLE "res\\UpdateM.bmp" +UPDATEX BITMAP DISCARDABLE "res\\UpdateX.bmp" +DIRECTXD BITMAP DISCARDABLE "res\\DirectxD.bmp" +DIRECTXM BITMAP DISCARDABLE "res\\DirectxM.bmp" +DIRECTXU BITMAP DISCARDABLE "res\\DirectxU.bmp" +DIRECTXX BITMAP DISCARDABLE "res\\DirectxX.bmp" +UNINSTALLD BITMAP DISCARDABLE "res\\UninstallD.bmp" +UNINSTALLM BITMAP DISCARDABLE "res\\UninstallM.bmp" +UNINSTALLU BITMAP DISCARDABLE "res\\UninstallU.bmp" +UNINSTALLX BITMAP DISCARDABLE "res\\UninstallX.bmp" +UPDATEU BITMAP DISCARDABLE "res\\UpdateU.BMP" +UPDATED BITMAP DISCARDABLE "res\\UpdateD.bmp" +ANIM0 BITMAP DISCARDABLE "res\\Anim0.BMP" +ANIM1 BITMAP DISCARDABLE "res\\Anim1.BMP" +ANIM2 BITMAP DISCARDABLE "res\\Anim2.BMP" +ANIM3 BITMAP DISCARDABLE "res\\Anim3.BMP" +ANIM4 BITMAP DISCARDABLE "res\\Anim4.bmp" +ANIM5 BITMAP DISCARDABLE "res\\Anim5.bmp" +ANIM6 BITMAP DISCARDABLE "res\\Anim6.bmp" +ANIM7 BITMAP DISCARDABLE "res\\Anim7.bmp" +ANIM8 BITMAP DISCARDABLE "res\\Anim8.bmp" +HELPD BITMAP DISCARDABLE "res\\HelpD.bmp" +HELPM BITMAP DISCARDABLE "res\\HelpM.bmp" +HELPU BITMAP DISCARDABLE "res\\HelpU.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_UPDATEDLG_USERMSG1 "A new version of Descent 3 is available!!! Press the OK button to download it." + IDS_UPDATEDLG_USERMSG2 "Received %d bytes out of %d bytes (%d%%)." + IDS_D3LAUNCH_DLGTITLE "Descent 3 Launcher" + IDS_D3LAUNCH_URL_ERR1 "The operating system is out of memory or resources." + IDS_D3LAUNCH_URL_ERR2 "The .EXE file is invalid (non-Win32 .EXE or error in .EXE image)." + IDS_D3LAUNCH_URL_ERR3 "The operating system denied access to the specified file." + IDS_D3LAUNCH_URL_ERR4 "The filename association is incomplete or invalid.\r\n(You need to have a default Internet browser installed)" + IDS_D3LAUNCH_URL_ERR5 "The DDE transaction could not be completed because other DDE transactions were being processed." + IDS_D3LAUNCH_URL_ERR6 "The DDE transaction failed." + IDS_D3LAUNCH_URL_ERR7 "The DDE transaction could not be completed because the request timed out." + IDS_D3LAUNCH_URL_ERR8 "The specified dynamic-link library was not found." + IDS_D3LAUNCH_URL_ERR9 "There was not enough memory to complete the operation." + IDS_D3LAUNCH_URL_ERR10 "A sharing violation occurred." + IDS_D3LAUNCH_URL_ERR11 "No web browser found. There isn't one installed or if \r\none is installed, it isn't set to be the default browser.\r\n" + IDS_D3LAUNCH_URL_ERR12 "Unknown error occurred." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_D3LAUNCHDLG_NODD "DirectDraw could not be initialized on your system. DirectDraw v6.0 or higher\nis required in order to play Descent 3." + IDS_D3LAUNCHDLG_NODDT "Attention!" + IDS_D3LAUNCHDLG_SETUP "Descent 3 Setup" + IDS_D3LAUNCHDLG_RM_ERR "Error Loading README.TXT" + IDS_D3LAUNCHDLG_LNCH_ERR "Error Launching Descent 3" + IDS_3D_DETECT_NO3D "No device selected" + IDS_AUDIOTAB_A3D1 "Aureal sound card detected, but you need updated drivers.\n Download them from www.a3d.com" + IDS_AUDIOTAB_A3D2 "This is non-Aureal-certified A3D!\nPlease upgrade your drivers at www.a3d.com" + IDS_AUDIOTAB_NO_SOUND "No Sound" + IDS_JOYSTICKTAB_ERR1 "Error loading Joy.cpl" + IDS_JOYSTICKTAB_NONE "None" + IDS_UPDATEDLG_GVN_MSG1 "Attempting to Initialize Winsock" + IDS_UPDATEDLG_NO_CON "Cannot connect to patch server, may be down.\n Verify that you have an active internet connection and try again later." + IDS_UPDATEDLG_ERROR "Error!" + IDS_UPDATEDLG_GVN_MSG2 "Downloading Version Info File" + IDS_UPDATEDLG_NO_DL "Couldn't download Version File!" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_UPDATEDLG_NO_FIND "Couldn't parse Version file!" + IDS_UPDATEDLG_WAIT "Waiting for User" + IDS_UPDATEDLG_SRV "Successfully Read Version Info" + IDS_UPDATEDLG_UTD "Your Descent 3 version %d.%d.%d is currently up to date." + IDS_UPDATEDLG_UTDT "Determination: No Update Necessary" + IDS_UPDATEDLG_YES_ERR1 "Error opening version.nfo file - please try re-updating" + IDS_UPDATEDLG_PF_ERR1 "Couldn't Download Patchfile. Verify you have enough diskspace." + IDS_UPDATEDLG_PATCHING "Patching Descent 3 to version %d.%d.%d" + IDS_UPDATEDLG_GET_FILE "Getting File: %s" + IDS_UPDATEDLG_CANT_PATCH "Couldn't Process Patchfile" + IDS_UPDATEDLG_SKIPPING "Skipping: %s" + IDS_UPDATEDLG_PATCH_OK "Patching Process Successful." + IDS_UPDATEDLG_SUCCESS "Success!" + IDS_UPDATEDLG_NO_PATCH_LIB + "Patch Library not found. Cannot Patch Descent 3." + IDS_UPDATEDLG_DL_FILE "Downloading File..." + IDS_UPDATEDLG_INIT_CON "Initializing Connection..." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_UPDATEDLG_WS_ERR "Error loading Winsock!" + IDS_UPDATEDLG_CON_OK "Connecting..." + IDS_UPDATEDLG_CON_SHUTDOWN "Shutting down connection..." + IDS_UPDATEDLG_WAITING "Waiting..." + IDS_SPEEDTAB_LOW "Low (Example system: 200 MHz, 32 MB RAM, Direct3D)" + IDS_SPEEDTAB_MEDIUM "Medium (Example system: 300 MHz, 32 MB RAM, Glide)" + IDS_SPEEDTAB_HIGH "High (Example system: 300 MHz, 64 MB RAM, Glide)" + IDS_SPEEDTAB_VERY_HIGH "Very High (Example system: 400 MHz, 128 MB RAM, Glide)" + IDS_UPDATEDLG_LNCH_UPD1 "The Descent 3 Launcher needs to be updated to a newer version.\nIt will now be shutdown, modified, and then restarted.\n\nThis may take several seconds..." + IDS_UPDATEDLG_LNCH_UPD2 "The Descent 3 Launcher needs to be updated to a newer version.\nHowever, the Update Launcher executable could not be found (or could not be accessed).\n\nTherefore, the Launcher cannot be updated at this time." + IDS_UPDATEDLG_LNCH_UPD3 "The Descent 3 Launcher needs to be updated to a newer version.\nHowever, the replacement executable or patch file could not be accessed.\n\nTherefore, the Launcher cannot be updated at this time." + IDS_UPDATEDLG_LNCH_UPD_TITLE "Launcher Update" + IDS_UPDATEDLG_BEG_PATCH "Beginning Patching..." + IDS_UPDATEDLG_PATCH_COMPLETE "Patching Complete!" + IDS_UPDATEDLG_PATCH_FAILED "Patching Failed!" + IDS_UPDATEDLG_PATCH_ERROR "Patching Error" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_UPDATEDLG_PROCESSING "Processing %s" + IDS_UPDATEDLG_FILE_COMPLETE "File Complete!" + IDS_UPDATEDLG_SEARCHING "Searching for systems to update..." + IDS_UPDATEDLG_WNDMSG_MAIN "Now connecting to the Descent 3 Patch Server." + IDS_UPDATEDLG_WNDMSG_STATUS "Please wait..." + IDS_UPDATEDLG_USERMSG3 "Now updating Descent 3 to Version %d.%d.%d" + IDS_SITESELECTDLG_SITE_NAME "Site Name" + IDS_SITESELECTDLG_SITE_ADDRESS "URL" + IDS_SITESELECTDLG_SITE_LOCATION "Location" + IDS_SITESELECTDLG_MUST_SELECT "You must select a download site." + IDS_SITESELECTDLG_SELECT_TITLE "Site Selection" + IDS_UPDATEDLG_BADPARMS "Bad parameters were given.\n\nRemote file path: \t%s\nLocal file path: \t%s\n" + IDS_UPDATEDLG_CANT_WRITE_FILE "Could not write out to the file (%s)." + IDS_UPDATEDLG_CANT_PARSE_URL "Could not parse the given URL (%s)." + IDS_UPDATEDLG_BAD_FILE_OR_DIR + "A bad file or directory was encountered.\n\nRemote file path: \t%s\nLocal file path: \t%s\n" + IDS_UPDATEDLG_HOST_NOT_FOUND "The host could not be located (%s)." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_UPDATEDLG_NO_MEMORY "Out of memory!" + IDS_UPDATEDLG_CANCELLED "The update has been cancelled." + IDS_UPDATEDLG_UNKNOWN_ERROR + "The launcher was unable to contact the server. Please verify that your network connection is valid and working properly." + IDS_UPDATEDLG_DOWNLOAD_ERROR "File Download Message" + IDS_SITESELECTDLG_PARSE_ERROR + "The site info file could not be opened and parsed." + IDS_UPDATEDLG_DONE_UPDATING "Done Updating." + IDS_UPDATEDLG_CONTINUE_MSG + "Patching complete! Press the OK button to exit." + IDS_UPDATEDLG_NO_MOTD "Sorry, there is no message of the day." + IDS_UPDATEDLG_DL_MOTD "Downloading the Message of the Day" + IDS_UPDATEDLG_GOT_MOTD "Successfully Read the Message of the Day" + IDS_UPDATEDLG_NODL_MOTD "Could Not Download the Message of the Day" + IDS_AUDIOTAB_CARD_MISSING + "Your currently selected device (%s)\ncould not be detected.\n\nYou must select another device." + IDS_AUDIOTAB_WARNING "Warning!" + IDS_DIRECTXTAB_OK "Ok" + IDS_D3LAUNCH_NO_CD "Descent 3 CD not located. Please insert Descent 3 CD #1 and select OK to continue." + IDS_D3LAUNCH_CD_ERROR "Error Reading CD." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_DIRECTXTAB_NTMSG "Windows NT has DirectX built in. If you are running NT 4.0 you should have Service Pack 3 (SP3) installed. For detailed information on SP3 (including download links), go to:\n\nhttp://www.microsoft.com/support/winnt/nt4sp3.htm" + IDS_DIRECTXTAB_NTNOTICE "Windows NT Notice" + IDS_DIRECTXTAB_LOAD_ERROR "Error loading DirectX 6.1" + IDS_D3LAUNCHDLG_NO_UNINSTALL "No uninstall information found." + IDS_D3LAUNCHDLG_COULDNT_UNINSTALL "Couldn't Uninstall" + IDS_D3LAUNCHDLG_WARNING_PROMPT + "Are you sure you want to delete '%s' and all of its components?" + IDS_D3LAUNCHDLG_WARNING_TITLE "Confirm File Deletion" + IDS_D3LAUNCHDLG_UNINSTALL_ERROR "Error Launching Uninstaller" + IDS_D3LAUNCHDLG_PLAY_BTN "Play" + IDS_D3LAUNCHDLG_SETUP_BTN "Setup" + IDS_D3LAUNCHDLG_UPDATE_BTN "Auto-Update" + IDS_D3LAUNCHDLG_README_BTN "View Readme" + IDS_D3LAUNCHDLG_DIRECTX_BTN "Install Drivers" + IDS_D3LAUNCHDLG_UNINSTALL_BTN "Uninstall" + IDS_D3LAUNCHDLG_INSTALL_BTN "Install" + IDS_D3LAUNCHDLG_STRAIGHTTOSETUP_MSG + "Since this is your first time running Descent 3, you will now be automatically taken to the Setup window. \n\nIMPORTANT NOTE:\nIt is important that you view each section of the Setup window and configure it appropriately. Press the Help button if you have questions about a particular section. Once you are satisfied with your settings, select the OK button at the bottom of the Setup window to save them." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_D3LAUNCHDLG_STRAIGHTTOSETUP_TITLE "Welcome to Descent 3!" + IDS_D3LAUNCHDLG_PLAY_WARNING_MSG + "Before playing Descent 3, it is highly recommended that you fully configure your game from Setup (this means configuring each of the Setup Tabs before pressing the OK button).\n\nDo you wish to proceed and play Descent 3 anyway?" + IDS_D3LAUNCHDLG_FILE_NOT_FOUND "File Not Found Error" + IDS_D3LAUNCH_NO_HELP "The following help file could not be located:\n\n%s" + IDS_SPEEDTAB_SPEED_PROMPT + "Setup has determined a default detail level for your computer that is different from the one currently selected. If you decide to use this new setting, one or more of Descent 3's detail options will be altered to better suit the speed of your system.\n\nDo you wish to use the new detail level?" + IDS_SPEEDTAB_SPEED_TITLE "New Detail Level Determined" + IDS_D3LAUNCHDLG_WEBPAGE_BTN "Visit us!" + IDS_D3LAUNCHDLG_PXO_BTN "Play online!" + IDS_D3LAUNCHDLG_NO_RENDERER_MSG + "You must select a rendering device before playing Descent 3. This can be easily done by pressing the Setup button and then selecting the Video Tab. From there, you can detect all the devices available on your system and choose one." + IDS_D3LAUNCHDLG_NO_RENDERER_TITLE "No Rendering Device Selected!" + IDS_D3LAUNCHDLG_DEMO_ONLY_MSG + "Sorry, this option is not available in the demo version.\n\nDirectX 6.1 can be downloaded directly from Microsoft:\nhttp://www.microsoft.com/directx/download.asp" + IDS_D3LAUNCHDLG_DEMO_ONLY_TITLE "Not Available In Demo" + IDS_D3LAUNCH_DEMO_DLGTITLE "Descent 3 Demo Launcher" + IDS_VIDEOTAB_DXVERSION_TITLE "DirectX 6.0 Required" + IDS_VIDEOTAB_DXVERSION_MSG + "In order to play Descent 3 using Direct3D, you must have DirectX 6.0 installed. Click on the DirectX Setup Tab for information on obtaining DirectX 6.0." + IDS_D3LAUNCHDLG_DXVERSION_TITLE "DirectX 3.0 Required" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_D3LAUNCHDLG_DXVERSION_MSG + "In order to play Descent 3, you must have DirectX 3.0 or greater installed on your system.\n\n For information on obtaining DirectX, select the Setup button and then click on the DirectX Tab." + IDS_D3LAUNCHDLG_NOMEM_TITLE "Low Memory!" + IDS_D3LAUNCHDLG_NOMEM_MSG + "Your system may not have enough memory to reliably play Descent 3. It is reccomended that you free some disk space and reboot before trying to play.\n\nDo you want to continue anyway?" + IDS_PLEASE_WAIT_MSG "Please Wait..." + IDS_VIDEOTAB_SCANNING "Scanning Video Devices" + IDS_AUDIOTAB_SCANNING "Scanning Audio Devices" + IDS_JOYSTICKTAB_SCANNING "Scanning Input Devices" + IDS_VIDEOTAB_MTOD_MSG "More than one rendering device has been detected.\n\nYou need to select one of them from the Rendering Device drop-down list box." + IDS_VIDEOTAB_MTOD_TITLE "Multiple Video Devices Detected" + IDS_SPEEDTAB_NOT_DETECTED "Not detected" + IDS_UPDATEDLG_NOREGVER_MSG + "The Descent 3 Auto-Update program could not find your current game Version in the system registry.\n\nThis should be corrected by starting up the game, exiting the game, and then running the Auto-Update program." + IDS_UPDATEDLG_NOREGVER_TITLE "Unable to Determine User's Version" + IDS_DIRECTXTAB_UPD_REC "Update Recommended" + IDS_SPEEDTAB_CUSTOM "Custom" + IDS_D3LAUNCHDLG_SPD_MSG "You must allow Setup to configure your Default Detail Level setting before playing Descent 3 for the first time.\n\nTo do this, simply press the Setup button from the main menu and click on the Speed Tab. Then, press the ""Detect System Properties"" button to determine the recommended detail level setting for your system (answer ""Yes"" if prompted about changing your settings)." + IDS_D3LAUNCHDLG_SPD_TITLE "Detail Level Setting Not Configured" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_D3LAUNCHDLG_LAUNCH_ERRMSG + "The following error occurred while trying to launch ""%s"":\n\n" + IDS_D3LAUNCHDLG_CONTEST_MSG + "Based on the date your computer is set to, it appears that the $50,000 Descent 3 tournament is still running.\n\nFor more information, visit the Tournament Web Page at:\n%s\n\nWould you like to go to this page right now?" + IDS_D3LAUNCHDLG_CONTEST_TITLE + "The Descent 3 Tournament Is Still Running! " + IDS_D3LAUNCHDLG_DXERR_SUCCESS "The setup finished successfully." + IDS_D3LAUNCHDLG_DXERR_SUCCESS_RESTART + "The setup finished successfully.\n\nHowever, you must reboot your machine for the changes to take effect." + IDS_D3LAUNCHDLG_DXERR_BADSOURCESIZE + "The setup failed because a file's size could not be verified or was incorrect." + IDS_D3LAUNCHDLG_DXERR_BADSOURCETIME + "The setup failed because a file's date and time could not be verified or were incorrect." + IDS_D3LAUNCHDLG_DXERR_BADWINDOWSVERSION + "DirectX does not support the Windows version on this system." + IDS_D3LAUNCHDLG_DXERR_CANTFINDDIR + "The setup program could not find the working directory." + IDS_D3LAUNCHDLG_DXERR_CANTFINDINF + "ERROR: A required .inf file could not be found." + IDS_D3LAUNCHDLG_DXERR_INTERNAL "An internal error has occurred." + IDS_D3LAUNCHDLG_DXERR_NOCOPY + "The setup failed because a file's version could not be verified or was incorrect." + IDS_D3LAUNCHDLG_DXERR_NOTPREINSTALLEDONNT + "The version of Windows NT/Windows 2000 on this system does not contain the current version of DirectX. An older version of DirectX may be present, or DirectX may be absent all together." + IDS_D3LAUNCHDLG_DXERR_OUTOFDISKSPACE + "The setup program failed because it ran out of disk space during the installation." + IDS_D3LAUNCHDLG_DXERR_SOURCEFILENOTFOUND + "The setup failed because one of the required source files could not be found." + IDS_D3LAUNCHDLG_DXERR_UNKNOWNOS + "The operating system on this system is not currently supported." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_D3LAUNCHDLG_DXERR_USERHITCANCEL + "The Cancel button was pressed before the application was fully installed." + IDS_D3LAUNCHDLG_DXERR_TITLE "DirectX Setup" + IDS_D3LAUNCHDLG_DSETUP_ERR_MSG1 "Could not locate dsetup.dll" + IDS_D3LAUNCHDLG_DSETUP_ERR_MSG2 + "Could not obtain DirectXSetup from dsetup.dll" + IDS_D3LAUNCHDLG_DSETUP_ERR_TITLE "DirectSetup Error!" + IDS_GLSETUP_ERROR "Error Running GLSetup" + IDS_LANG_ENGLISH "English" + IDS_LANG_FRENCH "French" + IDS_LANG_GERMAN "German" + IDS_LANG_ITALIAN "Italian" + IDS_LANG_SPANISH "Spanish" + IDS_D3LAUNCH_OEMV3_DLGTITLE "Descent 3: SOL ASCENT for Voodoo3 Launcher" + IDS_D3LAUNCH_OEMA2_DLGTITLE "Descent 3: SOL ASCENT for Aureal Launcher" + IDS_D3LAUNCH_OEMKM_DLGTITLE + "Descent 3: SOL ASCENT for Pentium III Launcher" + IDS_D3LAUNCHDLG_UPDPRMT_MSG + "From time to time new versions of Descent 3 are made available that contain bug fixes and other improvements. Therefore we suggest you periodically check for updates by clicking on the Auto-Update button.\n\nWould you like to check for updates now?" + IDS_D3LAUNCHDLG_UPDPRMT_TITLE "Update Prompt" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_D3LAUNCH_OEM_DLGTITLE "Descent 3: SOL ASCENT Launcher" + IDS_D3LAUNCH_DEMO2_DLGTITLE "Descent 3 Demo 2 Launcher" + IDS_OPENGL_WARNING_MSG "WARNING: We have found many OpenGL drivers to be incomplete or buggy. If you are using a card with a Voodoo chipset, we strongly recommend you select Glide. For other cards, we suggest you try Direct3D if you experience problems running under OpenGL.\n" + IDS_OPENGL_WARNING_TITLE "OpenGL Warning" + IDS_NOTGLIDE_TITLE "Renderer Selection Warning" + IDS_NOTGLIDE_MSG "WARNING: If you are using a card with a Voodoo chipset, we strongly recommend you choose 3Dfx Glide as your Selected Renderer." + IDS_PROFANITY_MSG "Would you like to enable certain features of Descent 3 that would help prevent you from receiving profane or indecent messages from other players in a multiplayer game?\n\nNOTE: You can change these settings later if you wish." + IDS_PROFANITY_TITLE "Multiplayer Profanity Filter Settings" + IDS_GLSETUP_EXPIRED_MSG "This version of GLSetup has expired. Please visit the GLSetup web site at http://www.glsetup.com to download the release version of GLSetup." + IDS_FINDFAST_MSG "Descent 3 was unable to shut down FindFast on your computer.\n\nWould you like to run Descent 3 anyway?" + IDS_FINDFAST_TITLE "FindFast Shutdown Failed" + IDS_OK "OK" + IDS_CANCEL "Cancel" + IDS_HELP "Help" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif +#include "res\D3Launch.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/D3Launch/D3LaunchDlg.cpp b/D3Launch/D3LaunchDlg.cpp new file mode 100644 index 00000000..46b0f7a5 --- /dev/null +++ b/D3Launch/D3LaunchDlg.cpp @@ -0,0 +1,1891 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/D3LaunchDlg.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 78 10/18/99 5:40p Jeff + * passthru any command line arguments into Descent 3 + * + * 77 8/20/99 9:55a Nate + * D3 OEM General now starts Ereg + * + * 76 6/10/99 6:28p Nate + * Added files for Setup button fix + * + * 75 6/09/99 2:46p Nate + * Minor changes for different builds + * + * 74 5/23/99 11:44a Nate + * Added change to make sure the DDraw dll gets freed when launcher exits. + * + * 73 5/23/99 1:21a Nate + * Made FindFast Disabling default to "always" + * + * 72 5/22/99 12:28a Samir + * findfast user interface and detection code added to launcher. + * + * 71 5/20/99 2:28p Nate + * Changed GLSetup CD path + * + * 70 5/20/99 12:53p Nate + * Added GLSetup window, EAX mixer support, and CHFlight+Mouseman Mode + * options + * + * 69 5/07/99 11:23a Nate + * Added support for a launcher config file + * + * 68 4/27/99 10:41p Nate + * Added profanity filter prompt + * + * 67 4/25/99 1:55p Nate + * Removed Auto-Update prompt for D3 release + * + * 66 4/21/99 7:17p Nate + * Added "-nolightmaps" switch for LOW_DETAIL setting + * + * 65 4/19/99 11:26p Nate + * Added OpenGL warning message + * + * 64 4/15/99 12:03p Nate + * Added "Descent 3 Demo 2" build type + * + * 63 4/08/99 1:13p Nate + * Added Pentium III detection + * + * 62 4/07/99 3:27p Nate + * Added reselection of old palette when done drawing launcher background + * + * 61 3/29/99 3:14p Nate + * Added OEM_GENERIC + * + * 60 3/19/99 10:18a Nate + * Added OEM_GENERIC compile type + * + * 59 3/12/99 3:29p Nate + * Added more multi-language support + * + * 58 3/02/99 5:45p Nate + * Lots of little changes/fixes + * + * 57 2/28/99 5:29p Nate + * Added Auto-Update prompt + * + * 56 2/26/99 12:50p Nate + * Changed OEM_Voodoo3 names + * + * 55 2/24/99 8:37p Nate + * Various little dialog changes, added "Install Drivers" dialog + * + * 54 2/24/99 1:46p Nate + * Added multi-language support + * + * 53 2/22/99 4:11p Nate + * Added NO_MESSAGE checking to button strings + * + * 52 2/17/99 2:23p Nate + * Added some OEM changes + * + * 51 2/15/99 1:41p Nate + * Added DirectX installation through DirectSetup + * + * 50 2/10/99 1:56p Nate + * Added code for DirectX 6.1 Installation + * + * 49 2/05/99 3:51p Nate + * Added conditional compilation directives for OEM support + * + * 48 1/15/99 2:11p Nate + * Updated the tournament info prompt. + * + * 47 1/14/99 11:06a Nate + * Added tournament prompt dialog. + * + * 46 12/14/98 10:11a Nate + * Added the whacking of gamma related environment variables (for Kevin) + * + * 45 11/30/98 3:01p Nate + * The dedicated server can now be run without a video card selected. + * + * 44 11/09/98 1:35p Nate + * Made the error message for launching the main executable more helpful. + * + * 43 11/06/98 4:56p Nate + * User can now select highlighted button by pressing Enter. + * + * 42 11/05/98 2:16p Nate + * Added keyboard support + * + * 41 10/30/98 12:09p Nate + * Fixed clicking on light problem. + * + * 40 10/18/98 6:09p Nate + * + * 39 10/18/98 5:53p Nate + * + * 38 10/15/98 7:30p Nate + * + * 37 10/15/98 11:31a Nate + * Added Launcher Sound toggling + * + * 36 10/13/98 3:03p Nate + * More fixes and changes. + * + * 35 10/12/98 8:17p Nate + * Added -lowmem command line switch for kevin + * + * 34 10/10/98 2:33p Nate + * More fixes. + * + * 33 10/08/98 6:23p Nate + * Fixed a few bugs. + * + * 32 10/02/98 7:08p Nate + * Added animation button + * + * 31 10/01/98 3:51p Nate + * Changed some file names and paths. + * + * 30 9/30/98 5:16p Nate + * Added Icon to "Demo Only" message box + * + * 29 9/30/98 2:01p Nate + * Added "Not available in Demo" message boxes. + * + * 28 9/29/98 2:23p Nate + * Pressing play now launches descent3.exe + * + * 27 9/25/98 6:58p Nate + * User cannot "Play" now unless he has selected a PreferredRenderer other + * than "None" + * + * 26 9/23/98 3:30p Nate + * Added "demo" conditional compilation + * + * 25 9/22/98 3:33p Nate + * Added conditional compiling to help system (can toggle between HTML and + * standard windows help) + * + * 24 9/22/98 11:33a Nate + * Added support for logo button text. + * + * 23 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 22 9/18/98 5:19p Nate + * Enabled the help buttons for the Setup tabs. + * + * 21 9/17/98 5:59p Nate + * "README.TXT file not found" error is now handled by the launcher rather + * than notepad + * + * 20 9/17/98 2:09p Nate + * Added StraightToSetup messages. + * + * 19 9/16/98 3:23p Nate + * Added straight to setup processing + * + * 18 9/14/98 3:47p Nate + * Added deletion of memDC's after use. + * + * 17 9/13/98 2:40p Nate + * Added re-selecting of default bitmaps and palettes for the device + * contexts. + * + * 16 9/10/98 5:17p Nate + * Added text message capability to bitmap buttons + * + * 15 9/09/98 1:10p Nate + * Now reads in the Uninstall application DisplayName from registry. + * + * 14 9/09/98 12:24p Nate + * Added Uninstall functionality. + * + * 13 9/08/98 11:05a Nate + * The background bitmap is now drawn in OnEraseBkgnd() rather than in + * OnPaint() - this eliminates the gray background flicker on startup + * + * 12 9/04/98 10:18a Nate + * Made it so light won't flicker for a certain time after startup. + * + * 11 9/03/98 6:57p Nate + * Fixed StretchBlt() problem by doing some 256 color conversions + * + * 10 9/02/98 6:42p Nate + * Added improved sound support. + * + * 9 9/01/98 7:15p Nate + * Major Revision #2 + * + * 8 8/31/98 6:44p Nate + * Major Revision + * + * 7 8/25/98 6:15p Nate + * Added the Message of the Day to the Auto Update Dialog + * + * 6 8/24/98 7:06p Nate + * Added new AutoUpdate features, and fixed display glitches + * + * 5 8/17/98 10:35a Nate + * Added Keyboard Type page to Setup + * + * 4 8/12/98 9:21a Nate + * Fixed "gray-button-background" flicker + * + * 3 8/10/98 10:44a Nate + * Added Language selection support + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +// D3LaunchDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "afxpriv.h" +#include "afxext.h" +#include "D3Launch.h" +#include "D3LaunchDlg.h" +#include "UpdateDlg.h" +#include "DirectXTab.h" +#include "JoystickTab.h" +#include "VideoTab.h" +#include "AudioTab.h" +#include "SpeedTab.h" +#include "NetworkTab.h" +#include "KeyboardTab.h" +#include "DriversDlg.h" +#include "3D_detect.h" +#include "OS_Config.h" +#include "LaunchNames.h" +#include "GLSetupDlg.h" +#include "FindFastDlg.h" +#include "SetupPropSheet.h" + +#include "dsetup.h" + +#include +#include +#include +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// Globals +CString szTitle; +CD3LaunchDlg *pLaunchDlg; + +UINT light_off_time; // Counts the number of msecs light has been off +UINT startup_time; // Counts msecs from startup +UINT anim_frame_time; // Counts msecs between animation frames + +bool mouse_moved; // flag to indicate if mouse has been moved +POINT last_mouse_pos; // records the last mouse position + +// Store the proper IDs for the bitmap buttons here: +static UINT ButtonIDs[NUM_BITMAP_BUTTONS] = { + IDC_BTN_PLAY, + IDC_BTN_SETUP, + IDC_BTN_UPDATE, + IDC_BTN_README, + IDC_BTN_DIRECTX, + IDC_BTN_UNINSTALL, + IDC_BTN_WEBPAGE, + IDC_BTN_PXO, + ID_HELP, + IDC_BTN_QUIT // NOTE: Make this the last one (it uses different sounds) +}; + +// Store the proper string IDs for the bitmap buttons here: +// NOTE: Use NO_MESSAGE if no message is desired +#define NO_MESSAGE 0 +static UINT ButtonStringIDs[NUM_BITMAP_BUTTONS] = { + IDS_D3LAUNCHDLG_PLAY_BTN, + IDS_D3LAUNCHDLG_SETUP_BTN, + IDS_D3LAUNCHDLG_UPDATE_BTN, + IDS_D3LAUNCHDLG_README_BTN, + IDS_D3LAUNCHDLG_DIRECTX_BTN, + IDS_D3LAUNCHDLG_UNINSTALL_BTN, + IDS_D3LAUNCHDLG_WEBPAGE_BTN, + IDS_D3LAUNCHDLG_PXO_BTN, + NO_MESSAGE, + NO_MESSAGE +}; + +// Store the proper text alignments for the bitmap buttons here: +static UINT ButtonOrientations[NUM_BITMAP_BUTTONS] = { + LEFT_ORIENTED_BTN, + LEFT_ORIENTED_BTN, + LEFT_ORIENTED_BTN, + RIGHT_ORIENTED_BTN, + RIGHT_ORIENTED_BTN, + RIGHT_ORIENTED_BTN, + TOP_ORIENTED_BTN, + TOP_ORIENTED_BTN, + LEFT_ORIENTED_BTN, + LEFT_ORIENTED_BTN +}; + + +///////////////////////////////////////////////////////////////////////////// +// CD3LaunchDlg dialog + +CD3LaunchDlg::CD3LaunchDlg(CWnd* pParent /*=NULL*/) + : CDialog(CD3LaunchDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CD3LaunchDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void CD3LaunchDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CD3LaunchDlg) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CD3LaunchDlg, CDialog) + //{{AFX_MSG_MAP(CD3LaunchDlg) + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + ON_WM_CREATE() + ON_BN_CLICKED(IDC_BTN_QUIT, OnBtnQuit) + ON_BN_CLICKED(IDC_BTN_SETUP, OnBtnSetup) + ON_BN_CLICKED(IDC_BTN_WEBPAGE, OnBtnWebpage) + ON_BN_CLICKED(IDC_BTN_README, OnBtnReadme) + ON_BN_CLICKED(IDC_BTN_PLAY, OnBtnPlay) + ON_WM_TIMER() + ON_WM_LBUTTONDOWN() + ON_BN_CLICKED(IDC_BTN_UPDATE, OnBtnUpdate) + ON_WM_ERASEBKGND() + ON_BN_CLICKED(IDC_BTN_PXO, OnBtnPxo) + ON_BN_CLICKED(IDC_BTN_UNINSTALL, OnBtnUninstall) + ON_BN_CLICKED(IDC_BTN_LIGHT, OnBtnLight) + ON_BN_CLICKED(IDC_BTN_DIRECTX, OnBtnDirectx) + ON_WM_QUERYNEWPALETTE() + ON_WM_PALETTECHANGED() + ON_MESSAGE(WM_STRAIGHT_TO_SETUP, OnStraightToSetup) + ON_WM_HELPINFO() + ON_MESSAGE(WM_COMMANDHELP,OnCommandHelp) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CD3LaunchDlg message handlers + +BOOL CD3LaunchDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + // TODO: Add extra initialization here + int j; + + pLaunchDlg=this; + + srand( (unsigned)time( NULL ) ); + + m_timerID=SetTimer(MOUSE_TIMER_ID,MAIN_TIMER_DELAY,NULL); + + // Dim all System Menu options we don't want + CMenu *sysmenu=GetSystemMenu(FALSE); + if(sysmenu!=NULL) { + sysmenu->EnableMenuItem(0,MF_BYPOSITION | MF_GRAYED); + sysmenu->EnableMenuItem(2,MF_BYPOSITION | MF_GRAYED); + sysmenu->EnableMenuItem(4,MF_BYPOSITION | MF_GRAYED); + } + + CBitmap *dlgBmap; + + dlgBmap = &(theApp.m_bkBmap); + + RECT rectClient; + dlgBmap->GetObject(sizeof(BITMAP), &m_bmInfo); + GetClientRect(&rectClient); + + // Calculate the bitmap dimension modifiers + DlgWidthModifier=double(rectClient.right)/double(m_bmInfo.bmWidth); + DlgHeightModifier=double(rectClient.bottom)/double(m_bmInfo.bmHeight); + + char msg1[256]; + sprintf(msg1,"WidthMod=%f, HeightMod=%f\n",DlgWidthModifier,DlgHeightModifier); + OutputDebugString(msg1); + + // If they are close to being one, just make them one + if(DlgWidthModifier>0.99 && DlgWidthModifier<1.01) DlgWidthModifier=1.0; + if(DlgHeightModifier>0.99 && DlgHeightModifier<1.01) DlgHeightModifier=1.0; + + // Calculate the size and position of the background bitmap + m_size.cx = long(m_bmInfo.bmWidth*DlgWidthModifier); + m_size.cy = long(m_bmInfo.bmHeight*DlgHeightModifier); + + m_pt.x = 0; + m_pt.y = 0; + + //CClientDC dc(this); + + //VERIFY( m_dcMem.CreateCompatibleDC(&dc)); + //m_dcMem.SelectObject(dlgBmap); + + // Setup the "pushable" bitmap buttons + for(j=0; jm_hObject != NULL ) { + dc.SelectPalette( palette, FALSE ); + dc.RealizePalette(); + } + dc.StretchBlt(0,0,m_size.cx,m_size.cy,&memDC,0,0,m_bmInfo.bmWidth,m_bmInfo.bmHeight,SRCCOPY); + */ + + // Do not call CDialog::OnPaint() for painting mesages + } +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR CD3LaunchDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + +int CD3LaunchDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CDialog::OnCreate(lpCreateStruct) == -1) + return -1; + + // TODO: Add your specialized creation code here + + + // set the window title + SetWindowText( szTitle ); + + return 0; +} + +void CD3LaunchDlg::OnBtnQuit() +{ + // Play quit button pressed (shutdown) sound + PlaySound("NormalBtnPressedSnd",TRUE,TRUE); + + // TODO: Add your control notification handler code here + EndDialog(0); +} + +void CD3LaunchDlg::OnBtnSetup() +{ + // TODO: Add your control notification handler code here + CSetupPropSheet sheet("Setup"); + + // Play button pressed sound + PlaySound("NormalBtnPressedSnd",TRUE,FALSE); + +#if (defined(DEMO) || defined(DEMO2)) + // Show the Interplay tournament prompt if necessary + DisplayTournamentPrompt(); +#endif + + if(os_config_read_uint(szSectionName,"ProfanityPrevention",9999)==9999) { + CString title, msg; + title.Format(IDS_PROFANITY_TITLE); + msg.Format(IDS_PROFANITY_MSG); + if(MessageBox(msg,title,MB_YESNO|MB_ICONQUESTION)==IDYES) + os_config_write_uint(NULL, "ProfanityPrevention", 1); + else + os_config_write_uint(NULL, "ProfanityPrevention", 0); + } + + // Display Setup Window + CString setup_title; + setup_title.LoadString(IDS_D3LAUNCHDLG_SETUP); + sheet.Construct(setup_title); + + CDirectXTab directXtab; + CVideoTab videotab; + CAudioTab audiotab; + CJoystickTab joytab; + CSpeedTab speedtab; + CNetworkTab networktab; + CKeyboardTab keyboardtab; + + // Turn off the HELP and APPLY buttons + //sheet.m_psh.dwFlags &= (~PSH_HASHELP); + sheet.m_psh.dwFlags |= PSH_NOAPPLYNOW; + //directXtab.m_psp.dwFlags &= (~PSP_HASHELP); + //videotab.m_psp.dwFlags &= (~PSP_HASHELP); + //audiotab.m_psp.dwFlags &= (~PSP_HASHELP); + //joytab.m_psp.dwFlags &= (~PSP_HASHELP); + //speedtab.m_psp.dwFlags &= (~PSP_HASHELP); + //networktab.m_psp.dwFlags &= (~PSP_HASHELP); + //keyboardtab.m_psp.dwFlags &= (~PSP_HASHELP); + + sheet.AddPage(&directXtab); + sheet.AddPage(&videotab); + sheet.AddPage(&audiotab); + sheet.AddPage(&joytab); + sheet.AddPage(&speedtab); + sheet.AddPage(&networktab); + sheet.AddPage(&keyboardtab); + + if ( sheet.DoModal() == IDOK ) { + if(theApp.m_straight_to_setup) { + os_config_write_uint(szSectionName, "StraightToSetup", 0); + theApp.m_straight_to_setup=0; + } + if(DetailLevelConfigured) + os_config_write_uint(szSectionName, "DetailLevelConfigured", 1); +#ifdef USE_MULTI_LANGUAGES + if(NewLanguageSelected) { + int lang_type=os_config_read_uint(szSectionName,"LanguageType",LANGUAGE_ENGLISH); + SetLanguageDLL(lang_type); + RefreshDialog(); + + // Copy over the appropriate help files + CopyHelpFiles(TRUE); + } +#endif + + // Get the currently selected renderer type + RendererType renderer_id = (RendererType)os_config_read_uint(NULL, "PreferredRenderer", RENDERER_NONE); + + // If they detected renderers, set vsync for jason + if(RenderersDetected) { + int vsync_enabled; + + if(renderer_id==RENDERER_DIRECT3D) + vsync_enabled=1; + else + vsync_enabled=0; + + os_config_write_uint(NULL, "RS_vsync", vsync_enabled); + RenderersDetected=FALSE; + } + + // Display the openGL warning message + if(renderer_id==RENDERER_OPENGL) { + if(os_config_read_uint(NULL, "OpenGLWarningShown", 0)==0) { + CString title, msg; + title.Format(IDS_OPENGL_WARNING_TITLE); + msg.Format(IDS_OPENGL_WARNING_MSG); + MessageBox(msg,title,MB_OK|MB_ICONINFORMATION); + os_config_write_uint(NULL, "OpenGLWarningShown", 1); + } + } + } + + DetailLevelConfigured=FALSE; + NewLanguageSelected=FALSE; +} + +void CD3LaunchDlg::OnBtnWebpage() +{ + // Play button pressed sound + PlaySound("NormalBtnPressedSnd",TRUE,FALSE); + + // TODO: Add your control notification handler code here + url_launch("http://www.outrage.com/"); +} + +void CD3LaunchDlg::OnBtnReadme() +{ + // Play button pressed sound + PlaySound("NormalBtnPressedSnd",TRUE,FALSE); + +#if (defined(DEMO)||defined(DEMO2)||defined(OEM_GENERIC)||defined(OEM_VOODOO3)||defined(OEM_AUREAL2)||defined(OEM_KATMAI)) + // Make sure readme.txt file exist + if( _access("readme.txt",0x00) == -1) { // does new executable exist? + CString readme_msg, readme_title; + readme_title.LoadString(IDS_D3LAUNCHDLG_FILE_NOT_FOUND); + readme_msg.LoadString(IDS_D3LAUNCHDLG_RM_ERR); + MessageBox( readme_msg, readme_title, MB_OK | MB_ICONEXCLAMATION); + return; + } + + // TODO: Add your control notification handler code here + STARTUPINFO si; + PROCESS_INFORMATION pi; + + memset( &si, 0, sizeof(STARTUPINFO) ); + si.cb = sizeof(si); + + BOOL ret = CreateProcess( NULL, // pointer to name of executable module + "notepad readme.txt", // pointer to command line string + NULL, // pointer to process security attributes + NULL, // pointer to thread security attributes + FALSE, // handle inheritance flag + CREATE_DEFAULT_ERROR_MODE, // creation flags + NULL, // pointer to new environment block + NULL, // pointer to current directory name + &si, // pointer to STARTUPINFO + &pi // pointer to PROCESS_INFORMATION + ); + + if ( !ret ) { + char *lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + // Display the string. + CString readme_msg; + readme_msg.LoadString(IDS_D3LAUNCHDLG_RM_ERR); + MessageBox( lpMsgBuf, readme_msg, MB_OK | MB_ICONEXCLAMATION); + + // Free the buffer. + LocalFree( lpMsgBuf ); + } +#else + // TODO: Add your control notification handler code here + STARTUPINFO si; + PROCESS_INFORMATION pi; + + memset( &si, 0, sizeof(STARTUPINFO) ); + si.cb = sizeof(si); + + BOOL ret = CreateProcess( NULL, // pointer to name of executable module + README_VIEWER_FNAME, // pointer to command line string + NULL, // pointer to process security attributes + NULL, // pointer to thread security attributes + FALSE, // handle inheritance flag + CREATE_DEFAULT_ERROR_MODE, // creation flags + NULL, // pointer to new environment block + NULL, // pointer to current directory name + &si, // pointer to STARTUPINFO + &pi // pointer to PROCESS_INFORMATION + ); + + if ( !ret ) { + char *lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + // Display the string. + CString readme_msg; + readme_msg.LoadString(IDS_D3LAUNCHDLG_RM_ERR); + MessageBox( lpMsgBuf, readme_msg, MB_OK | MB_ICONEXCLAMATION); + + // Free the buffer. + LocalFree( lpMsgBuf ); + } +#endif +} + +#define MAX_CMD_LINE_LEN 1024 +void CD3LaunchDlg::OnBtnPlay() +{ + CString msg, title, low_mem_switch, no_lightmaps_switch, chflight_switch, mouseman_switch; + bool dedicated_switch_set; + + // Play button pressed sound + PlaySound("NormalBtnPressedSnd",TRUE,TRUE); + + + // Check the command line to see if it's being run as dedicated server + char *command_line; + char command_line_temp[MAX_CMD_LINE_LEN+1]; + command_line = os_config_read_string(szSectionName, "CmdLineOptions", ""); + strncpy(command_line_temp,command_line,MAX_CMD_LINE_LEN); + command_line_temp[MAX_CMD_LINE_LEN]='\0'; + StringToLower(command_line_temp); + if(strstr(command_line_temp,"-dedicated ")==NULL) + dedicated_switch_set=FALSE; + else + dedicated_switch_set=TRUE; + + // Display message explaining that user must configure system + if(theApp.m_straight_to_setup) { + msg.LoadString(IDS_D3LAUNCHDLG_PLAY_WARNING_MSG); + title.LoadString(IDS_AUDIOTAB_WARNING); + if(MessageBox(msg,title,MB_YESNO|MB_ICONWARNING) != IDYES) return; + } + + // Display the message stating that user has not configured detail level + if(os_config_read_uint(NULL,"DetailLevelConfigured",0)==0) { + msg.LoadString(IDS_D3LAUNCHDLG_SPD_MSG); + title.LoadString(IDS_D3LAUNCHDLG_SPD_TITLE); + MessageBox(msg,title,MB_OK|MB_ICONWARNING); + return; + } + + // Display message if user has not selected a rendering device + if(!dedicated_switch_set && os_config_read_uint(NULL,"PreferredRenderer",RENDERER_NONE)==RENDERER_NONE) { + msg.LoadString(IDS_D3LAUNCHDLG_NO_RENDERER_MSG); + title.LoadString(IDS_D3LAUNCHDLG_NO_RENDERER_TITLE); + MessageBox(msg,title,MB_OK|MB_ICONWARNING); + return; + } + + // Display message if user does not have at least DirectX 3.0 installed + if(GetDirectXVersion()<3) { + CString title, msg; + title.LoadString(IDS_D3LAUNCHDLG_DXVERSION_TITLE); + msg.LoadString(IDS_D3LAUNCHDLG_DXVERSION_MSG); + MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); + return; + } + + // Display the low memory message + MEMORYSTATUS ms; + GlobalMemoryStatus(&ms); + low_mem_switch=""; + if((ms.dwAvailPageFile+ms.dwTotalPhys) < (80*1024*1024)) { + CString title, msg; + title.LoadString(IDS_D3LAUNCHDLG_NOMEM_TITLE); + msg.LoadString(IDS_D3LAUNCHDLG_NOMEM_MSG); + if(MessageBox(msg,title,MB_YESNO|MB_ICONWARNING) != IDYES) return; + low_mem_switch="-lowmem"; + } + +#if (defined(OEM_VOODOO3) || defined(OEM_AUREAL2) || defined(OEM_KATMAI)) + // Display the update recommendation message + if(os_config_read_uint(NULL,"UpdatePromptShown",0)==0) { + os_config_write_uint(NULL,"UpdatePromptShown",1); + msg.LoadString(IDS_D3LAUNCHDLG_UPDPRMT_MSG); + title.LoadString(IDS_D3LAUNCHDLG_UPDPRMT_TITLE); + if(MessageBox(msg,title,MB_YESNO|MB_ICONQUESTION)==IDYES) { + OnBtnUpdate(); + return; + } + } +#endif + + // display findfast dialog if needed. + HWND ffhwnd = ::FindWindow("Find Fast Indexer",NULL); + + if (ffhwnd) { + CFindFastDlg findfastdlg; + uint disable_ffast = os_config_read_uint(szSectionName, "FindFastDisable",1); + uint show_ffast_dlg = os_config_read_uint(szSectionName, "ShowFindFastDlg",1); + + if (show_ffast_dlg || !disable_ffast) { + int iDisableFF; + findfastdlg.m_AlwaysTerminateFF = disable_ffast ? TRUE : FALSE; + iDisableFF = findfastdlg.DoModal(); + if (iDisableFF == IDOK) { + os_config_write_uint(szSectionName, "FindFastDisable", findfastdlg.m_AlwaysTerminateFF ? 1 : 0); + disable_ffast = 1; + } else { + os_config_write_uint(szSectionName, "FindFastDisable", 0); + disable_ffast = 0; + } + os_config_write_uint(szSectionName, "ShowFindFastDlg", 0); + } + + if (disable_ffast) { + // Find fast was found + int num_shutdown_checks=0; + ::SendMessage(ffhwnd,WM_COMMAND,0xe141,0); + do { + Sleep(100); + ffhwnd = ::FindWindow("Find Fast Indexer", NULL); + num_shutdown_checks++; + } while(ffhwnd!=NULL && num_shutdown_checks<10); + + // If FindFast is still running, display warning prompt + if(ffhwnd!=NULL) { + msg.LoadString(IDS_FINDFAST_MSG); + title.LoadString(IDS_FINDFAST_TITLE); + if(MessageBox(msg,title,MB_YESNO|MB_ICONWARNING) != IDYES) return; + } + } + } + + // Read any option command line switches specified by user in Setup/Misc + char *cmd_line_options; + cmd_line_options = os_config_read_string(szSectionName, "CmdLineOptions", ""); + + // Get rid of any gamma related environment variables + SetEnvironmentVariable("SST_RGAMMA",NULL); + SetEnvironmentVariable("SST_GGAMMA",NULL); + SetEnvironmentVariable("SST_BGAMMA",NULL); + SetEnvironmentVariable("SST_GAMMA",NULL); + + SetEnvironmentVariable("SSTV2_RGAMMA",NULL); + SetEnvironmentVariable("SSTV2_GGAMMA",NULL); + SetEnvironmentVariable("SSTV2_BGAMMA",NULL); + SetEnvironmentVariable("SSTV2_GAMMA",NULL); + + // Don't use lightmaps if using lowest detail setting + if(os_config_read_uint(NULL,"PredefDetailSetting",MEDIUM_DETAIL)==LOW_DETAIL) { + no_lightmaps_switch="-nolightmaps"; + } else { + no_lightmaps_switch=""; + } + + // Set the Flightstick Pro Mode Switch if necessary + if(os_config_read_uint(szSectionName, "EnableCHFlight", 0)) { + chflight_switch="-chpro"; + } else { + chflight_switch=""; + } + + // Set the Mouseman Mode Switch if necessary + if(os_config_read_uint(szSectionName, "EnableMouseman", 0)) { + mouseman_switch="-mouseman"; + } else { + mouseman_switch=""; + } + + // TODO: Add your control notification handler code here + STARTUPINFO si; + PROCESS_INFORMATION pi; + CString ExecFile, CommandLine; + + ExecFile=GAME_EXECUTABLE_FNAME; + + // Get the command line arguments of the launcher and just pass + // them through to Descent 3. We have to becareful not to pass + // the launcher.exe name over (as it maybe too long, if the path is, + // for the argument system). There is no easy way to get this filename + // out, that is guaranteed. As the user might have a ' ' in their path + // to the launcher, or they might actually (*gasp*) rename the launcher. + // Or the might be running it from the root directory, so we can't look + // for a directory. Just a number of problems. So, what we'll do is + // look for the first - or + (that follows a space), we'll assume that + // the first command line argument will start with a - or a +. This + // method will fail if they install Descent 3 into a directory that has + // a space in the path, followed by a + or a -. But that won't cause us too much + // trouble, as just the rest of that path will get passed in as a command line + // argument. + int first_arg,launch_length; + CString launch_command; + launch_command = GetCommandLine(); + + launch_length = launch_command.GetLength(); + first_arg = launch_command.Find(" -",0); + if(first_arg==-1) + first_arg = launch_command.Find(" +",0); + if(first_arg==-1) + { + launch_command = ""; + }else + { + launch_command = launch_command.Right(launch_length - first_arg - 1); + } + + CommandLine.Format("%s %s %s %s %s %s %s %s",ExecFile,GAME_EXECUTABLE_SWITCH,low_mem_switch.GetBuffer(0),cmd_line_options,no_lightmaps_switch.GetBuffer(0),chflight_switch.GetBuffer(0),mouseman_switch.GetBuffer(0),launch_command.GetBuffer(0)); + + memset( &si, 0, sizeof(STARTUPINFO) ); + si.cb = sizeof(si); + + BOOL ret = CreateProcess( ExecFile.GetBuffer(0), // pointer to name of executable module + CommandLine.GetBuffer(0), // pointer to command line string + NULL, // pointer to process security attributes + NULL, // pointer to thread security attributes + FALSE, // handle inheritance flag + CREATE_DEFAULT_ERROR_MODE, // creation flags + NULL, // pointer to new environment block + NULL, // pointer to current directory name + &si, // pointer to STARTUPINFO + &pi // pointer to PROCESS_INFORMATION + ); + + if ( ret ) { + // If it executed correctly, exit this program + EndDialog(0); + } else { + char *lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + // Display the string + CString launch_msg, error_msg; + error_msg.Format(IDS_D3LAUNCHDLG_LAUNCH_ERRMSG,GAME_EXECUTABLE_FNAME); + error_msg += lpMsgBuf; + launch_msg.LoadString(IDS_D3LAUNCHDLG_LNCH_ERR); + MessageBox(error_msg, launch_msg, MB_OK | MB_ICONEXCLAMATION); + + // Free the buffer. + LocalFree( lpMsgBuf ); + } +} + + +// Checks if the mouse is currently over a button +bool CD3LaunchDlg::MouseOverButton(CButton *button) +{ + RECT btn_rect; + POINT point; + + // Check if launcher has focus first + if(GetActiveWindow()!=this) return FALSE; + + // Is the button disabled? + if(!button->IsWindowEnabled()) return FALSE; + + ::GetCursorPos(&point); + button->GetWindowRect(&btn_rect); + + // Check left and right button borders + if( point.x < btn_rect.left || point.x > btn_rect.right) + return FALSE; + + // Check left and right button borders + if( point.y < btn_rect.top || point.y > btn_rect.bottom) + return FALSE; + + // Mouse is over button + return TRUE; +} + +// Plays a sound (OPTIONAL: only if the this window is active) +void CD3LaunchDlg::PlaySound(LPSTR lpName, bool OnlyPlayIfActiveWnd, bool WaitUntilDone, bool WaitForStartup /*=TRUE*/) +{ + if(!LauncherSoundEnabled) return; + + if(WaitForStartup && startup_time < STARTUP_DELAY_TIME) return; + + if(!OnlyPlayIfActiveWnd || GetActiveWindow()==this) + PlayResource(lpName,WaitUntilDone); +} + +// Invalidates the button's window so that it is redrawn +void CD3LaunchDlg::RedrawButton(CButton *button) +{ + /* + RECT btn_rect; + + button->GetWindowRect(&btn_rect); + button->ScreenToClient(&btn_rect); + button->InvalidateRect(&btn_rect,FALSE); + */ + button->Invalidate(FALSE); +} + +// Hides or Un-Hides a button (depending on value of mHide) +void CD3LaunchDlg::HideButton(CBitmapButtonEx *button, bool mHide) +{ + RECT btn_rect; + + button->Hide(mHide); + + if(mHide) { + button->GetWindowRect(&btn_rect); + ScreenToClient(&btn_rect); + InvalidateRect(&btn_rect,FALSE); + } + else + RedrawButton(button); +} + +// Processes launcher's timing events +void CD3LaunchDlg::OnTimer(UINT nIDEvent) +{ + // TODO: Add your message handler code here and/or call default + if(nIDEvent==m_timerID) { + + // See if the mouse has been moved since last time + POINT curr_mouse_pos; + ::GetCursorPos(&curr_mouse_pos); + if(curr_mouse_pos.x!=last_mouse_pos.x || curr_mouse_pos.y!=last_mouse_pos.y) { + mouse_moved=TRUE; + last_mouse_pos.x=curr_mouse_pos.x; + last_mouse_pos.y=curr_mouse_pos.y; + } + + // Increment the startup time counter if necessary + if(startup_time < STARTUP_DELAY_TIME) + startup_time += MAIN_TIMER_DELAY; + + // Check if mouse is over any of the bitmap buttons + for(int j=0; j= STARTUP_DELAY_TIME) && (rand()%LIGHT_FLICKER_OFF_ODDS)==0) { + m_Light.Light(FALSE); + RedrawButton(&m_Light); + + // Set light off time to nothing + light_off_time=0; + + // Play light flicker sound + PlaySound("BulbFlickerSnd",TRUE,FALSE); + } + } + else { + // If light has been off enough time, turn it back on + light_off_time+=MAIN_TIMER_DELAY; + if(light_off_time >= MAX_LIGHT_OFF_TIME) { + m_Light.Light(TRUE); + RedrawButton(&m_Light); + } + } + + // Increment the animation frame time counter + anim_frame_time += MAIN_TIMER_DELAY; + + // Check if the animation bitmap should display the next frame + if(anim_frame_time >= MAX_ANIM_FRAME_TIME) { + m_Anim.DoNextAnimFrame(); + RedrawButton(&m_Anim); + anim_frame_time=0; + } + + } + + CDialog::OnTimer(nIDEvent); +} + + +void CD3LaunchDlg::OnLButtonDown(UINT nFlags, CPoint point) +{ + // TODO: Add your message handler code here and/or call default + + CDialog::OnLButtonDown(nFlags, point); + + // fake windows into thinking your clicking on the caption, + // lets you drag the window by clicking anywhere on the dialog + PostMessage( WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y)); +} + +void CD3LaunchDlg::OnBtnUpdate() +{ + // TODO: Add your control notification handler code here + int nResponse; + CUpdateDlg dlg; + + // Play button pressed sound + PlaySound("NormalBtnPressedSnd",TRUE,FALSE); + + nResponse = dlg.DoModal(); + + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + else if (nResponse == IDSHUTDOWN) + { + // This is only returned from the UpdateDlg when a Launcher update + // is supposed to take place. hence, the entire launcher must shutdown + EndDialog(0); + } + +} + +BOOL CD3LaunchDlg::PreCreateWindow(CREATESTRUCT& cs) +{ + // TODO: Add your specialized code here and/or call the base class + + return CDialog::PreCreateWindow(cs); +} + +// Sets the new language resource DLL +bool CD3LaunchDlg::SetLanguageDLL(int lang_type) +{ + // If a DLL is currently loaded, free it + if(theApp.m_hResInst!=NULL) { + FreeLibrary(theApp.m_hResInst); + theApp.m_hResInst=NULL; + } + + switch(lang_type) { + case LANGUAGE_ENGLISH: + AfxSetResourceHandle(theApp.m_hDefResInst); + return TRUE; + case LANGUAGE_FRENCH: + theApp.m_hResInst=LoadLibrary(FRENCH_RESOURCE_DLL); + break; + case LANGUAGE_GERMAN: + theApp.m_hResInst=LoadLibrary(GERMAN_RESOURCE_DLL); + break; + case LANGUAGE_ITALIAN: + theApp.m_hResInst=LoadLibrary(ITALIAN_RESOURCE_DLL); + break; + case LANGUAGE_SPANISH: + theApp.m_hResInst=LoadLibrary(SPANISH_RESOURCE_DLL); + break; + } + + if (theApp.m_hResInst != NULL) { + AfxSetResourceHandle(theApp.m_hResInst); + return TRUE; + } + + AfxSetResourceHandle(theApp.m_hDefResInst); + return FALSE; +} + +// This function can be called after a new resource DLL has +// been loaded in to update the dialog with a new title, etc. +void CD3LaunchDlg::RefreshDialog(void) +{ + int j; + + // set the window title + SetLauncherTitleString(); + SetWindowText( szTitle ); + + // Redraw the launcher bitmap images for new language + for(j=0; jGetDeviceCaps(RASTERCAPS) & RC_PALETTE && palette->m_hObject != NULL ) { + old_palette = pDC->SelectPalette( palette, FALSE ); + pDC->RealizePalette(); + } + + memDC.CreateCompatibleDC( pDC ); + old_bitmap=memDC.SelectObject( bitmap ); + + pDC->StretchBlt(0,0,m_size.cx,m_size.cy,&memDC,0,0,m_bmInfo.bmWidth,m_bmInfo.bmHeight,SRCCOPY); + + if(old_bitmap!=NULL) + memDC.SelectObject(old_bitmap); + + if(old_palette!=NULL) + pDC->SelectPalette(old_palette,FALSE); + + if(memDC.DeleteDC()==0) + OutputDebugString("DeleteDC() failed!\n"); + + //return CDialog::OnEraseBkgnd(pDC); + return 1; +} + +BOOL CD3LaunchDlg::DestroyWindow() +{ + // TODO: Add your specialized code here and/or call the base class + if (Dd_dll_handle!=NULL) { + FreeLibrary(Dd_dll_handle); + Dd_dll_handle=NULL; + } + + return CDialog::DestroyWindow(); +} + +void CD3LaunchDlg::OnBtnPxo() +{ + // Play button pressed sound + PlaySound("NormalBtnPressedSnd",TRUE,FALSE); + + // TODO: Add your control notification handler code here + url_launch("http://www.parallaxonline.com/"); + +} + + +void CD3LaunchDlg::OnBtnUninstall() +{ + // Play button pressed sound + PlaySound("NormalBtnPressedSnd",TRUE,FALSE); + + // TODO: Add your control notification handler code here + STARTUPINFO si; + PROCESS_INFORMATION pi; + char reg_command_line[1024]; + char app_name[1024]; + char *temp_str; + + // Grab the uninstall path + temp_str = os_config_read_string_ex( UNINSTALL_PATH, "UninstallString", NULL ); + if ( !temp_str ) { + CString msg, title; + msg.LoadString(IDS_D3LAUNCHDLG_NO_UNINSTALL); + title.LoadString(IDS_D3LAUNCHDLG_COULDNT_UNINSTALL); + MessageBox( msg, title, MB_OK | MB_ICONEXCLAMATION ); + return; + } + strcpy(reg_command_line,temp_str); + + // Grab the application display name + temp_str = os_config_read_string_ex( UNINSTALL_PATH, "DisplayName", NULL ); + if ( !temp_str ) { + CString msg, title; + msg.LoadString(IDS_D3LAUNCHDLG_NO_UNINSTALL); + title.LoadString(IDS_D3LAUNCHDLG_COULDNT_UNINSTALL); + MessageBox( msg, title, MB_OK | MB_ICONEXCLAMATION ); + return; + } + strcpy(app_name,temp_str); + + // display the "are you sure" prompt + CString warning_prompt, warning_title; + warning_prompt.Format(IDS_D3LAUNCHDLG_WARNING_PROMPT,app_name); + warning_title.LoadString(IDS_D3LAUNCHDLG_WARNING_TITLE); + int warning_ret = MessageBox( warning_prompt, warning_title, MB_OKCANCEL| MB_ICONQUESTION ); + if ( warning_ret == IDCANCEL ) { + return; + } + + // Launch the uninstaller + char command_line[1024]; + strcpy( command_line, reg_command_line ); + strcat( command_line, " -y" ); // Default to Yes. + + memset( &si, 0, sizeof(STARTUPINFO) ); + si.cb = sizeof(si); + + BOOL ret = CreateProcess( NULL, // pointer to name of executable module + command_line, // pointer to command line string + NULL, // pointer to process security attributes + NULL, // pointer to thread security attributes + FALSE, // handle inheritance flag + CREATE_DEFAULT_ERROR_MODE, // creation flags + NULL, // pointer to new environment block + NULL, // pointer to current directory name + &si, // pointer to STARTUPINFO + &pi // pointer to PROCESS_INFORMATION + ); + + if (ret) { + // If it executed correctly, exit this program + EndDialog(0); + + } else { + char *lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + // Display the string. + CString error_title; + error_title.LoadString(IDS_D3LAUNCHDLG_UNINSTALL_ERROR); + MessageBox( lpMsgBuf, error_title ); + + // Free the buffer. + LocalFree( lpMsgBuf ); + } +} + + +void CD3LaunchDlg::OnBtnLight() +{ + // Play light flicker sound + PlaySound("BulbFlickerSnd",TRUE,FALSE); + + // TODO: Add your control notification handler code here + +} + + +// Locates the user's CD-ROM drive +int CD3LaunchDlg::find_cd_drive(char *subdir) +{ + char oldpath[MAX_PATH]; + char volume[256]; + int i; + int cdrom_drive=-1; + + GetCurrentDirectory(MAX_PATH, oldpath); + + for (i = 0; i < 26; i++) + { + char path[]="d:\\"; + + path[0] = (char)('A'+i); + if (GetDriveType(path) == DRIVE_CDROM) { + cdrom_drive = -3; + GetVolumeInformation(path, volume, 256, NULL, NULL, NULL, NULL, 0); + if ( !stricmp(volume, CD1_VOLUME_NAME) || !stricmp(volume, CD2_VOLUME_NAME) ) { + if (!_chdir(path)) { + if (subdir==NULL || !_chdir(subdir)) { + cdrom_drive = i; + break; + } + } + } + } + } + + SetCurrentDirectory(oldpath); + return cdrom_drive; +} + +// return cd drive number (if found). Return < 0 if no cd drive located +int CD3LaunchDlg::launcher_get_CD_path(char *path, int prompt_for_cd, char *subdir) +{ + int cd_drive_num = -1; + + // locate the cd-rom + path[0] = 0; + while (1) { + int msgbox_choice; + cd_drive_num = find_cd_drive(subdir); + + if ( cd_drive_num >= 0 ) { + break; + } + + if ( !prompt_for_cd ) { + cd_drive_num = -1; + break; + } + + // ask if they want to try again + CString msg, title; + msg.LoadString(IDS_D3LAUNCH_NO_CD); + title.LoadString(IDS_D3LAUNCH_CD_ERROR); + msgbox_choice = MessageBox( msg, title, MB_OKCANCEL|MB_ICONWARNING ); + if ( msgbox_choice == IDCANCEL) { + return -1; + } + } + + return cd_drive_num; +} + + +void CD3LaunchDlg::OnBtnDirectx() +{ + // Play button pressed sound + PlaySound("NormalBtnPressedSnd",TRUE,FALSE); + +#if (defined(DEMO)||defined(DEMO2)) + CString demo_msg, demo_title; + demo_msg.LoadString(IDS_D3LAUNCHDLG_DEMO_ONLY_MSG); + demo_title.LoadString(IDS_D3LAUNCHDLG_DEMO_ONLY_TITLE); + MessageBox(demo_msg, demo_title, MB_OK|MB_ICONEXCLAMATION); + return; +#endif + + CDriversDlg dlg; + if(dlg.DoModal()==IDCANCEL) return; + + switch(dlg.m_Selection) { + case INSTALL_DIRECTX: + InstallDirectX(); + break; + case INSTALL_GLSETUP: + RunOpenGLSetup(); + break; + } +} + + +typedef int (CALLBACK *LPFN_DIRECTXSETUP)(HWND, LPSTR, DWORD); + +void CD3LaunchDlg::InstallDirectX() +{ + OSVERSIONINFO ver; + char CD_path[MAX_PATH]; + char DLL_path[MAX_PATH]; + int cd_drive_num; + + // check if running under NT + ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&ver); + if ( ver.dwPlatformId == VER_PLATFORM_WIN32_NT ) { + CString msg, title; + msg.LoadString(IDS_DIRECTXTAB_NTMSG); + title.LoadString(IDS_DIRECTXTAB_NTNOTICE); + MessageBox(msg, title); + return; + } + + cd_drive_num = launcher_get_CD_path(CD_path,1,"\\directx6"); + if ( cd_drive_num < 0 ) { + return; + } + + char original_path[MAX_PATH]; + _getcwd(original_path, MAX_PATH-1); + + sprintf(CD_path,"%c:\\", 'a' + cd_drive_num ); + strcat(CD_path, "directx6"); + _chdir(CD_path); + + HINSTANCE dsetup_dll_handle=NULL; + LPFN_DIRECTXSETUP pfn_DirectXSetup=NULL; + + // Check for the DirectXSetup dll, and open it + strcpy(DLL_path,CD_path); + strcat(DLL_path,"\\dsetup.dll"); + dsetup_dll_handle=LoadLibrary(DLL_path); + if(dsetup_dll_handle==NULL) { + CString msg, title; + msg.Format(IDS_D3LAUNCHDLG_DSETUP_ERR_MSG1); + title.Format(IDS_D3LAUNCHDLG_DSETUP_ERR_TITLE); + MessageBox(msg,title); + SetCurrentDirectory(original_path); + return; + } + + // Get the DirectXSetup function + pfn_DirectXSetup = (LPFN_DIRECTXSETUP)GetProcAddress(dsetup_dll_handle,"DirectXSetupA"); + if(pfn_DirectXSetup==NULL) { + CString msg, title; + msg.Format(IDS_D3LAUNCHDLG_DSETUP_ERR_MSG2); + title.Format(IDS_D3LAUNCHDLG_DSETUP_ERR_TITLE); + MessageBox(msg,title); + FreeLibrary(dsetup_dll_handle); + dsetup_dll_handle=NULL; + SetCurrentDirectory(original_path); + return; + } + + int rc=pfn_DirectXSetup(this->m_hWnd,CD_path,DSETUP_DIRECTX); + + CString err_msg, err_title; + err_title.Format(IDS_D3LAUNCHDLG_DXERR_TITLE); + switch(rc) { + case DSETUPERR_SUCCESS: + err_msg.Format(IDS_D3LAUNCHDLG_DXERR_SUCCESS); + MessageBox(err_msg,err_title); + break; + case DSETUPERR_SUCCESS_RESTART: + err_msg.Format(IDS_D3LAUNCHDLG_DXERR_SUCCESS_RESTART); + MessageBox(err_msg,err_title); + break; + case DSETUPERR_BADSOURCESIZE: + err_msg.Format(IDS_D3LAUNCHDLG_DXERR_BADSOURCESIZE); + MessageBox(err_msg,err_title); + break; + case DSETUPERR_BADSOURCETIME: + err_msg.Format(IDS_D3LAUNCHDLG_DXERR_BADSOURCETIME); + MessageBox(err_msg,err_title); + break; + case DSETUPERR_BADWINDOWSVERSION: + err_msg.Format(IDS_D3LAUNCHDLG_DXERR_BADWINDOWSVERSION); + MessageBox(err_msg,err_title); + break; + case DSETUPERR_CANTFINDDIR: + err_msg.Format(IDS_D3LAUNCHDLG_DXERR_CANTFINDDIR); + MessageBox(err_msg,err_title); + break; + case DSETUPERR_CANTFINDINF: + err_msg.Format(IDS_D3LAUNCHDLG_DXERR_CANTFINDINF); + MessageBox(err_msg,err_title); + break; + case DSETUPERR_INTERNAL: + err_msg.Format(IDS_D3LAUNCHDLG_DXERR_INTERNAL); + MessageBox(err_msg,err_title); + break; + case DSETUPERR_NOCOPY: + err_msg.Format(IDS_D3LAUNCHDLG_DXERR_NOCOPY); + MessageBox(err_msg,err_title); + break; + case DSETUPERR_NOTPREINSTALLEDONNT: + err_msg.Format(IDS_D3LAUNCHDLG_DXERR_NOTPREINSTALLEDONNT); + MessageBox(err_msg,err_title); + break; + case DSETUPERR_OUTOFDISKSPACE: + err_msg.Format(IDS_D3LAUNCHDLG_DXERR_OUTOFDISKSPACE); + MessageBox(err_msg,err_title); + break; + case DSETUPERR_SOURCEFILENOTFOUND: + err_msg.Format(IDS_D3LAUNCHDLG_DXERR_SOURCEFILENOTFOUND); + MessageBox(err_msg,err_title); + break; + case DSETUPERR_UNKNOWNOS: + err_msg.Format(IDS_D3LAUNCHDLG_DXERR_UNKNOWNOS); + MessageBox(err_msg,err_title); + break; + case DSETUPERR_USERHITCANCEL: + err_msg.Format(IDS_D3LAUNCHDLG_DXERR_USERHITCANCEL); + MessageBox(err_msg,err_title); + break; + }; + + FreeLibrary(dsetup_dll_handle); + dsetup_dll_handle=NULL; + + SetCurrentDirectory(original_path); +} + + +void CD3LaunchDlg::RunOpenGLSetup() +{ + // display the opengl setup dialog + CGLSetupDlg dlg; + + if(dlg.DoModal()==IDCANCEL) return; + + // run the install program + char CD_path[MAX_PATH]; + int cd_drive_num; + + cd_drive_num = launcher_get_CD_path(CD_path,1,"\\GLSetup"); + if ( cd_drive_num < 0 ) { + return; + } + + char original_path[MAX_PATH]; + _getcwd(original_path, MAX_PATH-1); + + sprintf(CD_path,"%c:\\", 'a' + cd_drive_num ); + strcat(CD_path, "GLSetup"); + _chdir(CD_path); + + // ok, now run GLSetup + STARTUPINFO si; + PROCESS_INFORMATION pi; + + memset( &si, 0, sizeof(STARTUPINFO) ); + si.cb = sizeof(si); + + BOOL ret = CreateProcess( "glsetup.exe", // pointer to name of executable module + NULL, // pointer to command line string + NULL, // pointer to process security attributes + NULL, // pointer to thread security attributes + FALSE, // handle inheritance flag + CREATE_DEFAULT_ERROR_MODE, // creation flags + NULL, // pointer to new environment block + NULL, // pointer to current directory name + &si, // pointer to STARTUPINFO + &pi // pointer to PROCESS_INFORMATION + ); + + if ( !ret ) { + char *lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + // Display the string. + CString err_title; + err_title.LoadString(IDS_GLSETUP_ERROR); + MessageBox( lpMsgBuf, err_title ); + + // Free the buffer. + LocalFree( lpMsgBuf ); + } + + SetCurrentDirectory(original_path); +} + + +BOOL CD3LaunchDlg::OnQueryNewPalette( ) +{ + OutputDebugString("OnQueryNewPalette() called.\n"); + + int j; + Invalidate(TRUE); + for(j=0; jSetState(true); + Sleep(80); + selected_button->SetState(false); + + // Trick main window into thinking that button has been clicked + ctrl_id=selected_button->GetDlgCtrlID(); + hwnd=selected_button->m_hWnd; + PostMessage(WM_COMMAND,(BN_CLICKED<<16) + ctrl_id,(long)hwnd); + + //CDialog::OnOK(); +} + + +#define TOURNAMENT_URL "http://www.interplay.com/descent3/ftourney.html" + +// Displays tournament contest web link prompt +void CD3LaunchDlg::DisplayTournamentPrompt(void) +{ + int rc, already_displayed; + CString msg, title; + + // If the prompt has already been displayed, exit + already_displayed=os_config_read_uint(szSectionName,"TournamentPromptDisplayed",0); + if(already_displayed) return; + + // Check the system date, if it is after July 1, 1999, exit + SYSTEMTIME sys_time; + GetSystemTime(&sys_time); + if(sys_time.wYear>1999) return; + if(sys_time.wYear==1999 && sys_time.wMonth>7) return; + if(sys_time.wYear==1999 && sys_time.wMonth==7 && sys_time.wDay>1) return; + //msg.Format("year=%d\nmonth=%d\nday=%d",sys_time.wYear,sys_time.wMonth,sys_time.wDay); + + msg.Format(IDS_D3LAUNCHDLG_CONTEST_MSG,TOURNAMENT_URL); + title.Format(IDS_D3LAUNCHDLG_CONTEST_TITLE); + + // Display the tournament contest web link prompt + rc=MessageBox(msg,title,MB_YESNO|MB_ICONQUESTION); + + // Store flag in registry so we don't display this message again + os_config_write_uint(szSectionName, "TournamentPromptDisplayed", 1); + + // If user selected "Yes", then display the web page + if(rc==IDYES) + url_launch(TOURNAMENT_URL); +} diff --git a/D3Launch/D3LaunchDlg.h b/D3Launch/D3LaunchDlg.h new file mode 100644 index 00000000..90ffeef5 --- /dev/null +++ b/D3Launch/D3LaunchDlg.h @@ -0,0 +1,233 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/D3LaunchDlg.h $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 28 3/02/99 5:45p Nate + * Lots of little changes/fixes + * + * 27 2/26/99 12:50p Nate + * Changed OEM_Voodoo3 names + * + * 26 2/24/99 8:37p Nate + * Various little dialog changes, added "Install Drivers" dialog + * + * 25 2/24/99 1:46p Nate + * Added multi-language support + * + * 24 2/15/99 1:41p Nate + * Added DirectX installation through DirectSetup + * + * 23 1/14/99 11:06a Nate + * Added tournament prompt dialog. + * + * 22 11/30/98 3:01p Nate + * The dedicated server can now be run without a video card selected. + * + * 21 11/06/98 4:56p Nate + * User can now select highlighted button by pressing Enter. + * + * 20 11/05/98 2:16p Nate + * Added keyboard support + * + * 19 10/18/98 5:53p Nate + * + * 18 10/10/98 2:33p Nate + * More fixes. + * + * 17 10/02/98 7:09p Nate + * Added animation button + * + * 16 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 15 9/16/98 3:23p Nate + * Added straight to setup processing + * + * 14 9/13/98 2:38p Nate + * + * 13 9/10/98 5:17p Nate + * Added text message capability to bitmap buttons + * + * 12 9/04/98 10:18a Nate + * Made it so light won't flicker for a certain time after startup. + * + * 11 9/03/98 6:57p Nate + * Fixed StretchBlt() problem by doing some 256 color conversions + * + * 10 9/02/98 6:42p Nate + * Added improved sound support. + * + * 9 9/01/98 7:15p Nate + * Major Revision #2 + * + * 8 8/31/98 6:44p Nate + * Major Revision + * + * 7 8/25/98 6:15p Nate + * Added the Message of the Day to the Auto Update Dialog + * + * 6 8/24/98 7:06p Nate + * Added new AutoUpdate features, and fixed display glitches + * + * 5 8/17/98 10:35a Nate + * Added Keyboard Type page to Setup + * + * 4 8/12/98 9:21a Nate + * Fixed "gray-button-background" flicker + * + * 3 8/10/98 10:44a Nate + * Added Language selection support + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +// D3LaunchDlg.h : header file +// + +#if !defined(AFX_D3LAUNCHDLG_H__9149CF3A_207D_11D2_8CBD_00A0C96ED60D__INCLUDED_) +#define AFX_D3LAUNCHDLG_H__9149CF3A_207D_11D2_8CBD_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +///////////////////////////////////////////////////////////////////////////// +// CD3LaunchDlg dialog +#include "BitmapButtonEx.h" + +// Main timer delay (in msecs) +#define MAIN_TIMER_DELAY 50 + +// Launcher shutdown code +#define IDSHUTDOWN -1 + +// Time between animation frames (in msecs) +#define MAX_ANIM_FRAME_TIME 100 + +// Number of animation frames +#define NUM_ANIM_FRAMES 9 + +// Chance of flicker is 1 in [ODDS VALUE] +#define LIGHT_FLICKER_OFF_ODDS 40 + +// Time light is off during flicker (in msecs) +#define MAX_LIGHT_OFF_TIME 100 + +// Delay time for light (it can't flicker for this long during startup) +#define STARTUP_DELAY_TIME 1500 + +#define MOUSE_TIMER_ID 1 + +#define NUM_BITMAP_BUTTONS 10 + + +class CD3LaunchDlg : public CDialog +{ +// Construction +public: + CD3LaunchDlg(CWnd* pParent = NULL); // standard constructor + bool MouseOverButton(CButton *button); // checks if mouse is over button + void RedrawButton(CButton *button); // marks button region for redraw + void RefreshDialog(void); // sets up launcher for new language + bool SetLanguageDLL(int lang_type); // sets up the new language resource DLL + + void PlaySound(LPSTR lpName, bool OnlyPlayIfActiveWnd, bool WaitUntilDone, bool WaitForStartup=TRUE); // Plays a sound + + void HideButton(CBitmapButtonEx *button, bool mHide); // Hides (or un-hides) a button + + void DisplayTournamentPrompt(void); // displays tournament contest web link prompt + + int launcher_get_CD_path(char *path, int prompt_for_cd, char *subdir); + int find_cd_drive(char *subdir); + + void InstallDirectX(void); // runs DirectXSetup from CD#1 + + void RunOpenGLSetup(void); // runs the GLSetup executable from CD#1 + + //CDC m_dcMem; // Compatible memory DC for dialog + //CBrush m_brush; // Handle of hollow brush + //CBrush m_bkBrush; // Handle of background brush + BITMAP m_bmInfo; // Bitmap info + CPoint m_pt; // Position of bitmap + CSize m_size; // Size of bitmap + + // Define all "pushable" bitmap buttons + CBitmapButtonEx m_Buttons[NUM_BITMAP_BUTTONS]; + + // Keep blinking light bitmap separate + CBitmapButtonEx m_Light; + + // Keep animation bitmap separate + CBitmapButtonEx m_Anim; + + // Timer ID variable + UINT m_timerID; + +// Dialog Data + //{{AFX_DATA(CD3LaunchDlg) + enum { IDD = IDD_D3LAUNCH_DIALOG }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CD3LaunchDlg) + public: + virtual BOOL DestroyWindow(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + //}}AFX_VIRTUAL + +// Implementation +protected: + HICON m_hIcon; + + // Generated message map functions + //{{AFX_MSG(CD3LaunchDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnBtnQuit(); + afx_msg void OnBtnSetup(); + afx_msg void OnBtnWebpage(); + afx_msg void OnBtnReadme(); + afx_msg void OnBtnPlay(); + afx_msg void OnTimer(UINT nIDEvent); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnBtnUpdate(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnBtnPxo(); + afx_msg void OnBtnUninstall(); + afx_msg void OnBtnLight(); + afx_msg void OnBtnDirectx(); + afx_msg BOOL OnQueryNewPalette(); + afx_msg void OnPaletteChanged( CWnd* pFocusWnd ); + afx_msg LONG OnStraightToSetup(UINT, LONG); + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); + afx_msg LRESULT OnCommandHelp(WPARAM wParam, LPARAM lParam); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +extern CString szTitle; +extern CD3LaunchDlg *pLaunchDlg; + +// pass this message to myself when initializing if I should go straight to the +// update dialog +#define WM_STRAIGHT_TO_SETUP (WM_USER + 10) + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_D3LAUNCHDLG_H__9149CF3A_207D_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/DirectXTab.cpp b/D3Launch/DirectXTab.cpp new file mode 100644 index 00000000..bb71397e --- /dev/null +++ b/D3Launch/DirectXTab.cpp @@ -0,0 +1,211 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/DirectXTab.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 9 2/16/99 6:09p Nate + * Changed DX version output from V.0 to V.x + * + * 8 10/14/98 5:52p Nate + * More fixes + * + * 7 10/08/98 6:23p Nate + * Fixed a few bugs. + * + * 6 9/22/98 3:33p Nate + * Added conditional compiling to help system (can toggle between HTML and + * standard windows help) + * + * 5 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 4 9/13/98 2:38p Nate + * Changed button to launch DirectX download webpage. + * + * 3 9/01/98 7:15p Nate + * Major Revision #2 + * + * 2 8/31/98 6:44p Nate + * Major Revision + * + * $NoKeywords: $ + */ + +// DirectXTab.cpp : implementation file +// + +#include "stdafx.h" +#include "afxpriv.h" +#include "afxext.h" +#include "d3launch.h" +#include "DirectXTab.h" +#include "PsTypes.h" +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern HINSTANCE Dd_dll_handle; + +///////////////////////////////////////////////////////////////////////////// +// CDirectXTab property page + +IMPLEMENT_DYNCREATE(CDirectXTab, CPropertyPage) + +CDirectXTab::CDirectXTab() : CPropertyPage(CDirectXTab::IDD) +{ + //{{AFX_DATA_INIT(CDirectXTab) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +CDirectXTab::~CDirectXTab() +{ +} + +void CDirectXTab::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDirectXTab) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDirectXTab, CPropertyPage) + //{{AFX_MSG_MAP(CDirectXTab) + ON_BN_CLICKED(IDC_GET_DX, OnGetDx) + ON_MESSAGE(WM_COMMANDHELP,OnCommandHelp) + ON_WM_HELPINFO() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDirectXTab message handlers + +BOOL CDirectXTab::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + // TODO: Add extra initialization here + LONG lResult; + HKEY hKey = NULL; + + if (Dd_dll_handle) { + lResult = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, // Where it is + "Software\\Microsoft\\DirectX", // name of key + NULL, // DWORD reserved + KEY_QUERY_VALUE, // Allows all changes + &hKey // Location to store key + ); + + if (lResult == ERROR_SUCCESS) { + char version[32]; + DWORD dwType, dwLen; + + dwLen = 32; + lResult = RegQueryValueEx( + hKey, // Handle to key + "Version", // The values name + NULL, // DWORD reserved + &dwType, // What kind it is + (ubyte *) version, // value to set + &dwLen // How many bytes to set + ); + + if (lResult == ERROR_SUCCESS) { + CString str; + + Dx_version = atoi(strstr(version, ".") + 1); + str.Format("%d.x (%s)", Dx_version, version); + GetDlgItem(IDC_DX_VERSION)->SetWindowText(str); + + } else { + int val; + DWORD dwType, dwLen; + + dwLen = 4; + lResult = RegQueryValueEx( + hKey, // Handle to key + "InstalledVersion", // The values name + NULL, // DWORD reserved + &dwType, // What kind it is + (ubyte *) &val, // value to set + &dwLen // How many bytes to set + ); + + if (lResult == ERROR_SUCCESS) { + CString str; + + Dx_version = val; + str.Format("%d.x", Dx_version); + GetDlgItem(IDC_DX_VERSION)->SetWindowText(str); + + } + } + + RegCloseKey(hKey); + } + } + + if (Dx_version >= 6) { + CString msg; + msg.LoadString(IDS_DIRECTXTAB_OK); + GetDlgItem(IDC_DX_STATUS)->SetWindowText(msg.GetBuffer(0)); + } + else if (Dx_version >= 3) { + CString msg; + msg.LoadString(IDS_DIRECTXTAB_UPD_REC); + GetDlgItem(IDC_DX_STATUS)->SetWindowText(msg.GetBuffer(0)); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +// Takes user to DirectX web page +void CDirectXTab::OnGetDx() +{ + url_launch("http://www.microsoft.com/directx/download.asp"); +} + + +void CDirectXTab::OnOK() +{ + // TODO: Add your specialized code here and/or call the base class + + CPropertyPage::OnOK(); +} + +BOOL CDirectXTab::OnHelpInfo(HELPINFO* pHelpInfo) +{ + // TODO: Add your message handler code here and/or call default +#ifdef USE_HTML_HELP_SYSTEM + CWaitCursor wc; + help_launch(DIRECTXTAB_HELP); + return 1; +#else + return CPropertyPage::OnHelpInfo(pHelpInfo); +#endif +} + +// Display the html help file +afx_msg LRESULT CDirectXTab::OnCommandHelp(WPARAM wParam, LPARAM lParam) +{ +#ifdef USE_HTML_HELP_SYSTEM + help_launch(DIRECTXTAB_HELP); + return 1; +#else + return CPropertyPage::OnCommandHelp(wParam,lParam); +#endif +} diff --git a/D3Launch/DirectXTab.h b/D3Launch/DirectXTab.h new file mode 100644 index 00000000..1cb8e383 --- /dev/null +++ b/D3Launch/DirectXTab.h @@ -0,0 +1,77 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/DirectXTab.h $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 4 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 3 9/01/98 7:15p Nate + * Major Revision #2 + * + * 2 8/31/98 6:44p Nate + * Major Revision + * + * $NoKeywords: $ + */ + +#if !defined(AFX_DIRECTXTAB_H__42877762_40B8_11D2_8CBD_00A0C96ED60D__INCLUDED_) +#define AFX_DIRECTXTAB_H__42877762_40B8_11D2_8CBD_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// DirectXTab.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDirectXTab dialog + +class CDirectXTab : public CPropertyPage +{ + DECLARE_DYNCREATE(CDirectXTab) + +// Construction +public: + CDirectXTab(); + ~CDirectXTab(); + +// Dialog Data + //{{AFX_DATA(CDirectXTab) + enum { IDD = IDD_PROPPAGE_DIRECTX }; + // NOTE - ClassWizard will add data members here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CDirectXTab) + public: + virtual void OnOK(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CDirectXTab) + virtual BOOL OnInitDialog(); + afx_msg void OnGetDx(); + afx_msg LRESULT OnCommandHelp(WPARAM wParam, LPARAM lParam); + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DIRECTXTAB_H__42877762_40B8_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/DriversDlg.cpp b/D3Launch/DriversDlg.cpp new file mode 100644 index 00000000..92db068a --- /dev/null +++ b/D3Launch/DriversDlg.cpp @@ -0,0 +1,79 @@ +// DriversDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "d3launch.h" +#include "DriversDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDriversDlg dialog + + +CDriversDlg::CDriversDlg(CWnd* pParent /*=NULL*/) + : CDialog(CDriversDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDriversDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_Selection=INSTALL_NONE; +} + + +void CDriversDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDriversDlg) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDriversDlg, CDialog) + //{{AFX_MSG_MAP(CDriversDlg) + ON_BN_CLICKED(IDC_DIRECTX_BUTTON, OnDirectxButton) + ON_BN_CLICKED(IDC_GLSETUP_BUTTON, OnGlsetupButton) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDriversDlg message handlers + +BOOL CDriversDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_Selection=INSTALL_NONE; + +#if (defined(OEM_VOODOO3) || defined(DISABLE_GLSETUP)) + CWnd *button; + button=GetDlgItem(IDC_GLSETUP_BUTTON); + if(button!=NULL) button->EnableWindow(FALSE); +#endif + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CDriversDlg::OnDirectxButton() +{ + m_Selection=INSTALL_DIRECTX; + CDialog::OnOK(); +} + +void CDriversDlg::OnGlsetupButton() +{ + m_Selection=INSTALL_GLSETUP; + CDialog::OnOK(); +} + +void CDriversDlg::OnOK() +{ + m_Selection=INSTALL_NONE; + CDialog::OnOK(); +} diff --git a/D3Launch/DriversDlg.h b/D3Launch/DriversDlg.h new file mode 100644 index 00000000..728ad57d --- /dev/null +++ b/D3Launch/DriversDlg.h @@ -0,0 +1,57 @@ +#if !defined(AFX_DRIVERSDLG_H__0325ACC0_CC01_11D2_A4E0_00A0C96ED60D__INCLUDED_) +#define AFX_DRIVERSDLG_H__0325ACC0_CC01_11D2_A4E0_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DriversDlg.h : header file +// + + +// Installation selections +#define INSTALL_NONE 0 +#define INSTALL_DIRECTX 1 +#define INSTALL_GLSETUP 2 + +///////////////////////////////////////////////////////////////////////////// +// CDriversDlg dialog + +class CDriversDlg : public CDialog +{ +// Construction +public: + CDriversDlg(CWnd* pParent = NULL); // standard constructor + + int m_Selection; + +// Dialog Data + //{{AFX_DATA(CDriversDlg) + enum { IDD = IDD_DRIVERS_DIALOG }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDriversDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDriversDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnDirectxButton(); + afx_msg void OnGlsetupButton(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DRIVERSDLG_H__0325ACC0_CC01_11D2_A4E0_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/FindFastDlg.cpp b/D3Launch/FindFastDlg.cpp new file mode 100644 index 00000000..2d007cf6 --- /dev/null +++ b/D3Launch/FindFastDlg.cpp @@ -0,0 +1,71 @@ +// FindFastDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "d3launch.h" +#include "FindFastDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFindFastDlg dialog + + +CFindFastDlg::CFindFastDlg(CWnd* pParent /*=NULL*/) + : CDialog(CFindFastDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CFindFastDlg) + m_AlwaysTerminateFF = FALSE; + //}}AFX_DATA_INIT +} + + +void CFindFastDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CFindFastDlg) + DDX_Check(pDX, IDC_FINDFASTCHKBOX, m_AlwaysTerminateFF); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CFindFastDlg, CDialog) + //{{AFX_MSG_MAP(CFindFastDlg) + ON_BN_CLICKED(IDC_FINDFASTCHKBOX, OnFindfastchkbox) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFindFastDlg message handlers + +void CFindFastDlg::OnFindfastchkbox() +{ + CButton *chkbox = (CButton *)GetDlgItem(IDC_FINDFASTCHKBOX); + CButton *no_btn = (CButton *)GetDlgItem(IDCANCEL); + + if (chkbox->GetCheck() == 1) { + no_btn->EnableWindow(FALSE); + } + else { + no_btn->EnableWindow(TRUE); + } +} + + +BOOL CFindFastDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CButton *no_btn = (CButton *)GetDlgItem(IDCANCEL); + + if (m_AlwaysTerminateFF) { + no_btn->EnableWindow(FALSE); // this should never happen anyway, but just in case. + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/D3Launch/FindFastDlg.h b/D3Launch/FindFastDlg.h new file mode 100644 index 00000000..9b7d5fad --- /dev/null +++ b/D3Launch/FindFastDlg.h @@ -0,0 +1,47 @@ +#if !defined(AFX_FINDFASTDLG_H__261D1580_0FD4_11D3_AF2D_00A0C94B8467__INCLUDED_) +#define AFX_FINDFASTDLG_H__261D1580_0FD4_11D3_AF2D_00A0C94B8467__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// FindFastDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CFindFastDlg dialog + +class CFindFastDlg : public CDialog +{ +// Construction +public: + CFindFastDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CFindFastDlg) + enum { IDD = IDD_FINDFASTDLG }; + BOOL m_AlwaysTerminateFF; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFindFastDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CFindFastDlg) + afx_msg void OnFindfastchkbox(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_FINDFASTDLG_H__261D1580_0FD4_11D3_AF2D_00A0C94B8467__INCLUDED_) diff --git a/D3Launch/GLSetupDlg.cpp b/D3Launch/GLSetupDlg.cpp new file mode 100644 index 00000000..c2022e96 --- /dev/null +++ b/D3Launch/GLSetupDlg.cpp @@ -0,0 +1,108 @@ +/* +* $Logfile: /DescentIII/Main/D3Launch/GLSetupDlg.cpp $ +* $Revision: 1.1.1.1 $ +* $Date: 2003-08-26 03:56:51 $ +* $Author: kevinb $ +* +* +* +* $Log: not supported by cvs2svn $ + * + * 2 5/20/99 12:53p Nate + * Added GLSetup window, EAX mixer support, and CHFlight+Mouseman Mode + * options +* +* $NoKeywords: $ +*/ + +// GLSetupDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "d3launch.h" +#include "GLSetupDlg.h" + +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CGLSetupDlg dialog + + +CGLSetupDlg::CGLSetupDlg(CWnd* pParent /*=NULL*/) + : CDialog(CGLSetupDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CGLSetupDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CGLSetupDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CGLSetupDlg) + DDX_Control(pDX, IDC_INSTALL_BUTTON, m_InstallButton); + DDX_Control(pDX, IDC_INFO3_STATIC, m_Info3Text); + DDX_Control(pDX, IDC_INFO2_STATIC, m_Info2Text); + DDX_Control(pDX, IDC_INFO_STATIC, m_Info1Text); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CGLSetupDlg, CDialog) + //{{AFX_MSG_MAP(CGLSetupDlg) + ON_BN_CLICKED(IDC_INSTALL_BUTTON, OnInstallButton) + ON_BN_CLICKED(IDC_VISIT_BUTTON, OnVisitButton) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CGLSetupDlg message handlers + +BOOL CGLSetupDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Check the system date, if it is after July 1999, the beta has expired + bool beta_expired=FALSE; + SYSTEMTIME sys_time; + + GetSystemTime(&sys_time); + if(sys_time.wYear>1999) + beta_expired=TRUE; + else if(sys_time.wYear==1999 && sys_time.wMonth>7) + beta_expired=TRUE; + + if(beta_expired) { + CString msg; + msg.LoadString(IDS_GLSETUP_EXPIRED_MSG); + m_Info1Text.SetWindowText(msg.GetBuffer(0)); + m_Info2Text.SetWindowText(""); + m_Info3Text.SetWindowText(""); + m_InstallButton.EnableWindow(FALSE); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CGLSetupDlg::OnInstallButton() +{ + CDialog::OnOK(); +} + +void CGLSetupDlg::OnVisitButton() +{ + url_launch("http://www.glsetup.com/"); +} + +void CGLSetupDlg::OnCancel() +{ + CDialog::OnCancel(); +} diff --git a/D3Launch/GLSetupDlg.h b/D3Launch/GLSetupDlg.h new file mode 100644 index 00000000..bd720db5 --- /dev/null +++ b/D3Launch/GLSetupDlg.h @@ -0,0 +1,69 @@ +/* +* $Logfile: /DescentIII/Main/D3Launch/GLSetupDlg.h $ +* $Revision: 1.1.1.1 $ +* $Date: 2003-08-26 03:56:51 $ +* $Author: kevinb $ +* +* +* +* $Log: not supported by cvs2svn $ + * + * 2 5/20/99 12:53p Nate + * Added GLSetup window, EAX mixer support, and CHFlight+Mouseman Mode + * options +* +* $NoKeywords: $ +*/ + +#if !defined(AFX_GLSETUPDLG_H__55A5E240_0E9F_11D3_A4E0_00A0C96ED60D__INCLUDED_) +#define AFX_GLSETUPDLG_H__55A5E240_0E9F_11D3_A4E0_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// GLSetupDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CGLSetupDlg dialog + +class CGLSetupDlg : public CDialog +{ +// Construction +public: + CGLSetupDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CGLSetupDlg) + enum { IDD = IDD_GLSETUP_DIALOG }; + CButton m_InstallButton; + CStatic m_Info3Text; + CStatic m_Info2Text; + CStatic m_Info1Text; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CGLSetupDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CGLSetupDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnInstallButton(); + afx_msg void OnVisitButton(); + virtual void OnCancel(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_GLSETUPDLG_H__55A5E240_0E9F_11D3_A4E0_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/Ia3dutil.h b/D3Launch/Ia3dutil.h new file mode 100644 index 00000000..209ab603 --- /dev/null +++ b/D3Launch/Ia3dutil.h @@ -0,0 +1,25 @@ +/*--------------------------------------------------------------------------- + * + * $Workfile: Ia3dutil.h $ + * + *--------------------------------------------------------------------------- + *$NoKeywords: $ + */ + +#ifndef _IA3DUTIL_H_ +#define _IA3DUTIL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +extern HRESULT A3dInitialize(void); +extern void A3dUninitialize(void); +extern HRESULT A3dCreate(GUID *,void **,IUnknown FAR *,DWORD); +extern HRESULT A3dRegister(void); + +#ifdef __cplusplus +}; +#endif + +#endif // _IA3DUTIL_H_ diff --git a/D3Launch/JoystickTab.cpp b/D3Launch/JoystickTab.cpp new file mode 100644 index 00000000..e111501d --- /dev/null +++ b/D3Launch/JoystickTab.cpp @@ -0,0 +1,739 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/JoystickTab.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 16 5/20/99 12:53p Nate + * Added GLSetup window, EAX mixer support, and CHFlight+Mouseman Mode + * options + * + * 15 2/22/99 2:46p Nate + * Fixed problem with long joystick names/descriptions + * + * 14 11/30/98 3:42p Nate + * Disabled Force Feedback checkbox for demo + * + * 13 10/12/98 7:13p Nate + * Fixed several bugs. + * + * 12 10/10/98 4:05p Nate + * Added detection/scanning window messages + * + * 11 10/08/98 6:23p Nate + * Fixed a few bugs. + * + * 10 9/22/98 3:33p Nate + * Added conditional compiling to help system (can toggle between HTML and + * standard windows help) + * + * 9 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 8 9/15/98 6:02p Nate + * Fixed double detection NT bug. + * + * 7 9/15/98 6:02p Nate + * Added Force Feedback detection. + * + * 6 9/02/98 6:42p Nate + * Added improved sound support. + * + * 5 9/01/98 7:15p Nate + * Major Revision #2 + * + * 4 8/31/98 6:44p Nate + * Major Revision + * + * 3 8/10/98 10:44a Nate + * Added Language selection support + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +// JoystickTab.cpp : implementation file +// + +#include "stdafx.h" +#include "afxpriv.h" +#include "afxext.h" +#include +#include +#include "D3Launch.h" +#include "JoystickTab.h" +#include "dinput.h" +#include "OS_Config.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// Declare the joystick data +JoystickData joystick_data[MAX_NUM_JOYSTICKS]; +int Num_joysticks=0; + +///////////////////////////////////////////////////////////////////////////// +// CJoystickTab property page + +IMPLEMENT_DYNCREATE(CJoystickTab, CPropertyPage) + +CJoystickTab::CJoystickTab() : CPropertyPage(CJoystickTab::IDD) +{ + //{{AFX_DATA_INIT(CJoystickTab) + //}}AFX_DATA_INIT +} + +CJoystickTab::~CJoystickTab() +{ +} + +void CJoystickTab::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CJoystickTab) + DDX_Control(pDX, IDC_CHFLIGHT_CHECK, m_CHFlightEnabled); + DDX_Control(pDX, IDC_MOUSEMAN_CHECK, m_MousemanEnabled); + DDX_Control(pDX, IDC_JOYSTICK_LIST, m_joystick_list); + DDX_Control(pDX, IDC_FF_ENABLED, m_ff_enabled); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CJoystickTab, CPropertyPage) + //{{AFX_MSG_MAP(CJoystickTab) + ON_BN_CLICKED(IDC_BTN_CALIBRATE, OnBtnCalibrate) + ON_BN_CLICKED(IDC_BTN_DETECT, OnBtnDetect) + ON_CBN_SELCHANGE(IDC_JOYSTICK_LIST, OnSelchangeJoystickList) + ON_MESSAGE(WM_COMMANDHELP,OnCommandHelp) + ON_WM_HELPINFO() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CJoystickTab message handlers + +int GetJoystickName(int joy_num,char *szRegKey,char *szReturnName); +int di_detect_joysticks(int cur_joy, CComboBox *box); + + +void CJoystickTab::OnBtnCalibrate() +{ + // TODO: Add your control notification handler code here + STARTUPINFO si; + PROCESS_INFORMATION pi; + + memset( &si, 0, sizeof(STARTUPINFO) ); + si.cb = sizeof(si); + + BOOL ret = CreateProcess( NULL, // pointer to name of executable module + "rundll32.exe shell32.dll,Control_RunDLL joy.cpl", // pointer to command line string + NULL, // pointer to process security attributes + NULL, // pointer to thread security attributes + FALSE, // handle inheritance flag + CREATE_DEFAULT_ERROR_MODE, // creation flags + NULL, // pointer to new environment block + NULL, // pointer to current directory name + &si, // pointer to STARTUPINFO + &pi // pointer to PROCESS_INFORMATION + ); + + if ( !ret ) { + char *lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + // Display the string. + CString err_msg; + err_msg.LoadString(IDS_JOYSTICKTAB_ERR1); + MessageBox( lpMsgBuf, err_msg, MB_OK | MB_ICONEXCLAMATION); + + // Free the buffer. + LocalFree( lpMsgBuf ); + } +} + + +// Detect all the joysticks +void CJoystickTab::DetectSticks() +{ + char str[1024]; + int j, max, cur_joy; + JOYCAPS JoyCaps; + + Num_joysticks=0; + //m_joystick_list.ResetContent(); + + // Add "none" option + CString none_msg; + none_msg.LoadString(IDS_JOYSTICKTAB_NONE); + strcpy(joystick_data[Num_joysticks].name,none_msg.GetBuffer(0)); + joystick_data[Num_joysticks].FF_capable=FALSE; + joystick_data[Num_joysticks].ID=JOYSTICK_NONE_ID; + Num_joysticks++; + + //index = m_joystick_list.InsertString(-1, none_msg); + + //m_joystick_list.SetItemData(index, 99999); // link joystick id to list item + //m_joystick_list.SetCurSel(0); + + //cur_joy = os_config_read_uint(szSectionName, "CurrentJoystick", 0); + cur_joy=0; + if (di_detect_joysticks(cur_joy, &m_joystick_list)==0) { + max = joyGetNumDevs(); + for (j=JOYSTICKID1; j1) + selected_stick=1; // First joystick in list + else + selected_stick=0; // None +/* + // Clear the list + m_joystick_list.ResetContent(); + + // Read in the selected joystick + cur_stick = os_config_read_uint(szSectionName, "CurrentJoystick", JOYSTICK_NONE_ID); + + // Fill the list with the detected joysticks + selected_stick=Num_joysticks-1; + for (i=0; iSetWindowText(joystick_data[selected_stick].name); + UpdateData(FALSE); + + // Set the FF checkbox is user wants to use FF + int ff_enabled = os_config_read_uint(szSectionName, "EnableJoystickFF", 1); + if (ff_enabled && joystick_data[selected_stick].FF_capable) { + m_ff_enabled.SetCheck(1); + } else { + m_ff_enabled.SetCheck(0); + } + UpdateData(FALSE); + + // Enable or disable the FF checkbox + GetDlgItem(IDC_FF_ENABLED,&hwnd); +#ifdef DEMO + ::EnableWindow(hwnd, FALSE); +#else + ::EnableWindow(hwnd, joystick_data[selected_stick].FF_capable); +#endif + + // Set the CHFlight checkbox is user wants to use that mode + if(os_config_read_uint(szSectionName, "EnableCHFlight", 0)) { + m_CHFlightEnabled.SetCheck(1); + } else { + m_CHFlightEnabled.SetCheck(0); + } + UpdateData(FALSE); + + // Set the Mouseman checkbox is user wants to use that mode + if(os_config_read_uint(szSectionName, "EnableMouseman", 0)) { + m_MousemanEnabled.SetCheck(1); + } else { + m_MousemanEnabled.SetCheck(0); + } + UpdateData(FALSE); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +// JAS: Taken from Nov 1996 Game Developer, page 49. +// Damn, that is some UGLY code! (But it works...) +/*---------------------------------------------------------------------*/ +int GetJoystickName(int joy_num,char *szRegKey,char *szReturnName) +/* + Description : Opens the MediaResources\Joysitick\mjstick.drv\JoystickSettings and + extracts Joystick%dOEMName string + Arguments : joy_num (r/o) - Joystick Number + szRegKey (r/o) - Registry Key of the msjstick.drv + ReturnName (r/w) - Return String for name listed in Control Panel + Returns : 0 for success 1 for failure +/*-----------------------------------------------------------------------*/ +{ + BYTE KeyStr[MAX_PATH] = REGSTR_PATH_JOYCONFIG; // found in regstr.h + BYTE KeyJoySetStr[MAX_PATH] = REGSTR_KEY_JOYSETTINGS; // found in Regstr.h + BYTE szOEMName[MAX_PATH]; // OEM name from Current Settings + HKEY ConfigKey; + HKEY JoyConfigKey; // Joystick Configuration + HKEY DriverKey; // Joystick Driver Key + HKEY OEMPropKey; + HKEY PropKey; + DWORD Length; + if( ERROR_SUCCESS != RegOpenKey( HKEY_LOCAL_MACHINE,REGSTR_PATH_JOYCONFIG,&ConfigKey ) ) + + { + return( 1 ); // It should never get here key received from Caps + } + + if( ERROR_SUCCESS != RegOpenKey( ConfigKey, szRegKey, &DriverKey ) ) + { + return( 1 ); // It should never get here key received from Caps + } + // Open CurrentSettings Key + + if( ERROR_SUCCESS != RegOpenKey( DriverKey, REGSTR_KEY_JOYCURR, &JoyConfigKey ) ) + { + return( 1 ); // It should never get here always a Current Settings + } + sprintf((char *)KeyStr,(char *)REGSTR_VAL_JOYNOEMNAME,joy_num+1); + Length=sizeof(szOEMName); // Get OEMNAME Configuration + + if( ERROR_SUCCESS != RegQueryValueEx( JoyConfigKey,(char *)KeyStr,NULL,NULL,(unsigned char *)&szOEMName,&Length)) + { + return( 1 ); // No OEM name listed return error + } + RegCloseKey( ConfigKey ); // Closes the registry Key + + // Open OEM Properties Key + if( ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,REGSTR_PATH_JOYOEM,&PropKey ) ) + { + return( 1 ); // It should never get here key received from Caps + } + + if( ERROR_SUCCESS != RegOpenKey( PropKey, (char *)szOEMName, &OEMPropKey ) ) + { + return( 1 ); // It should never get here if device is selected + } + Length=MAX_PATH; // Get Name as listed in Control Panel + + if( ERROR_SUCCESS != RegQueryValueEx( OEMPropKey,REGSTR_VAL_JOYOEMNAME,NULL,NULL,(unsigned char *)szReturnName,&Length)) + { + return( 1 ); // No OEM name listed return error + } + RegCloseKey( OEMPropKey ); // Closes the registry Key + return 0; + +} /* End GetJoystickName */ + + +void CJoystickTab::OnOK() +{ + // TODO: Add your specialized code here and/or call the base class + //int index; + int cur_joy = 0; + + if ( m_ff_enabled.GetCheck() ) { + os_config_write_uint( szSectionName, "EnableJoystickFF", 1 ); + } else { + os_config_write_uint( szSectionName, "EnableJoystickFF", 0 ); + } + + if ( m_CHFlightEnabled.GetCheck() ) { + os_config_write_uint( szSectionName, "EnableCHFlight", 1 ); + } else { + os_config_write_uint( szSectionName, "EnableCHFlight", 0 ); + } + + if ( m_MousemanEnabled.GetCheck() ) { + os_config_write_uint( szSectionName, "EnableMouseman", 1 ); + } else { + os_config_write_uint( szSectionName, "EnableMouseman", 0 ); + } + + /* + // save the joystick selected to be used in Descent 3 + index = m_joystick_list.GetCurSel(); + if (index >= 0) + cur_joy = joystick_data[index].ID; + + os_config_write_uint(szSectionName, "CurrentJoystick", cur_joy); + */ + OutputDebugString("Setting the joystick!\n"); + + CPropertyPage::OnOK(); +} + + +// Pointers to functions contained in DSOUND.dll +int Di_dll_loaded = 0; +HINSTANCE Di_dll_handle = NULL; +HRESULT (__stdcall *pfn_DirectInputCreate) (HINSTANCE, DWORD, LPDIRECTINPUT *, LPUNKNOWN) = NULL; + +// obtain the function pointers from the dsound.dll +void di_dll_get_functions() +{ + pfn_DirectInputCreate = (HRESULT (__stdcall *) (HINSTANCE, DWORD, LPDIRECTINPUT *, LPUNKNOWN)) GetProcAddress(Di_dll_handle, "DirectInputCreateA"); +} + +// Load the dsound.dll, and get funtion pointers +// exit: 0 -> dll loaded successfully +// !0 -> dll could not be loaded +int di_dll_load() +{ + if (!Di_dll_loaded) { + Di_dll_handle = LoadLibrary("dinput.dll"); + if (!Di_dll_handle) + return -1; + + di_dll_get_functions(); + Di_dll_loaded = 1; + } + + return 0; +} + +void di_dll_free() +{ + if (Di_dll_loaded) { + FreeLibrary(Di_dll_handle); + Di_dll_handle = NULL; + Di_dll_loaded = 0; + } +} + +typedef struct { + CComboBox *box; + int cur_joy; + int count; +} stuff; + +// Create storage for any temporary debug messages +char msg_buffer[1024]; + +// Callback function for enumerating ALL joysticks +BOOL CALLBACK enum_joysticks(LPCDIDEVICEINSTANCE lpddi, LPVOID ptr) +{ + int num; + stuff *stuffp = (stuff *) ptr; + + OutputDebugString("Found joystick in enum!\n"); + sprintf(msg_buffer,"%s (%s)\n", lpddi->tszProductName, lpddi->tszInstanceName); + OutputDebugString(msg_buffer); + + // Make sure it is a joystick + if (strnicmp(lpddi->tszInstanceName, "Joystick ", 9)) + return DIENUM_CONTINUE; + + // Get the joystick number + num = atoi(lpddi->tszInstanceName + 9) - 1; + sprintf(msg_buffer,"num=%d\n",num); + OutputDebugString(msg_buffer); + + // Fill in the data + sprintf(joystick_data[Num_joysticks].name, "%s (%s)", lpddi->tszProductName, lpddi->tszInstanceName); + joystick_data[Num_joysticks].FF_capable=FALSE; + joystick_data[Num_joysticks].ID=num; +/* + i = stuffp->box->InsertString(-1, joystick_data[Num_joysticks].name); + stuffp->box->SetItemData(i, num); + if (num == stuffp->cur_joy) + stuffp->box->SetCurSel(i); +*/ + + Num_joysticks++; + stuffp->count++; + + return DIENUM_CONTINUE; +} + +// Callback function for enumerating ONLY force feedback joysticks +BOOL CALLBACK enum_ff_joysticks(LPCDIDEVICEINSTANCE lpddi, LPVOID ptr) +{ + int i, num; + OutputDebugString("Found force feedback joystick in enum!\n"); + + sprintf(msg_buffer, "%s (%s)\n", lpddi->tszProductName, lpddi->tszInstanceName); + OutputDebugString(msg_buffer); + + // Make sure it is a joystick + if (strnicmp(lpddi->tszInstanceName, "Joystick ", 9)) + return DIENUM_CONTINUE; + + // Get the joystick number + num = atoi(lpddi->tszInstanceName + 9) - 1; + + // Set the ff_capable flag of this joystick + for(i=0;itszInstanceName); + if (strnicmp(buf, "Joystick ", 9)) + return DIENUM_CONTINUE; + + // Get the joystick number + num = atoi(buf + 9) - 1; + + // Get the name + sprintf(buf, "%s (%s)", lpddi->tszProductName, lpddi->tszInstanceName); + + // Fill in the data + strcpy(joystick_data[Num_joysticks].name,buf); + joystick_data[Num_joysticks].FF_capable=FALSE; + joystick_data[Num_joysticks].ID=num; + Num_joysticks++; + + i = stuffp->box->InsertString(-1, buf); + stuffp->box->SetItemData(i, num); + if (num == stuffp->cur_joy) + stuffp->box->SetCurSel(i); + + stuffp->count++; +*/ + return DIENUM_CONTINUE; +} + +int di_detect_joysticks(int cur_joy, CComboBox *box) +{ + HRESULT hr; + LPDIRECTINPUT di_joystick_obj; + stuff s; + + if (di_dll_load()) + return 0; + + if (!pfn_DirectInputCreate) { + di_dll_free(); + return 0; + } + + hr = pfn_DirectInputCreate(GetModuleHandle(NULL), DIRECTINPUT_VERSION, &di_joystick_obj, NULL); + if (FAILED(hr)) { + hr = pfn_DirectInputCreate(GetModuleHandle(NULL), 0x300, &di_joystick_obj, NULL); + if (FAILED(hr)) { + di_dll_free(); + return 0; + } + } + + s.count = 0; + s.box = box; + s.cur_joy = cur_joy; + + //hr = di_joystick_obj->EnumDevices(DIDEVTYPE_JOYSTICK, enum_joysticks, &s, DIEDFL_ALLDEVICES); + hr = di_joystick_obj->EnumDevices(DIDEVTYPE_JOYSTICK, enum_joysticks, &s, DIEDFL_ATTACHEDONLY); + if(hr==DIERR_INVALIDPARAM) { + OutputDebugString("Bad parm\n"); + } + if (FAILED(hr)) { + di_joystick_obj->Release(); + di_dll_free(); + return 0; + } + + // Enumerate any force feedback devices if at least one joystick was found + if(s.count>0) { + hr = di_joystick_obj->EnumDevices(DIDEVTYPE_JOYSTICK, enum_ff_joysticks, &s, DIEDFL_FORCEFEEDBACK | DIEDFL_ATTACHEDONLY); + if(hr==DIERR_INVALIDPARAM) { + OutputDebugString("Bad parm\n"); + } + if (FAILED(hr)) { + di_joystick_obj->Release(); + di_dll_free(); + return s.count; // return the number found in first enum + } + } + + di_joystick_obj->Release(); + + di_dll_free(); + + return s.count; +} + + +void CJoystickTab::OnBtnDetect() +{ + // TODO: Add your control notification handler code here + //int cur_stick, i; + int selected_stick; + HWND hwnd; + + // Set the wait cursor + CWaitCursor wc; + + // Display the scanning window + m_MsgDlg.m_ScanningMsg.LoadString(IDS_JOYSTICKTAB_SCANNING); + m_MsgDlg.m_WaitMsg.LoadString(IDS_PLEASE_WAIT_MSG); + m_MsgDlg.Create(IDD_MSG_DLG,this); + m_MsgDlg.ShowWindow(SW_SHOW); + m_MsgDlg.UpdateData(FALSE); + + // Detect all available joysticks + DetectSticks(); + + // Remove the scanning window + m_MsgDlg.DestroyWindow(); + + // Take the first joystick (if one exists) + if(Num_joysticks>1) + selected_stick=1; // First joystick in list + else + selected_stick=0; // None + +/* + // Clear the list + m_joystick_list.ResetContent(); + + // Read in the selected joystick + cur_stick = Num_joysticks-1; + + // Fill the list with the detected joysticks + selected_stick=Num_joysticks-1; + for (i=0; iSetWindowText(joystick_data[selected_stick].name); + UpdateData(FALSE); + + // Set the FF checkbox is user wants to use FF + int ff_enabled = os_config_read_uint(szSectionName, "EnableJoystickFF", 1); + if (ff_enabled && joystick_data[selected_stick].FF_capable) { + m_ff_enabled.SetCheck(1); + + } else { + m_ff_enabled.SetCheck(0); + } + + // Enable or disable the FF checkbox + GetDlgItem(IDC_FF_ENABLED,&hwnd); +#ifdef DEMO + ::EnableWindow(hwnd, FALSE); +#else + ::EnableWindow(hwnd, joystick_data[selected_stick].FF_capable); +#endif + UpdateData(FALSE); + +} + + +void CJoystickTab::OnSelchangeJoystickList() +{ + // TODO: Add your control notification handler code here + int index; + HWND hwnd; + + // Get the new joystick list position + index=m_joystick_list.GetCurSel(); + + // Enable or disable the FF checkbox + if(index>=0 && index= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// JoystickTab.h : header file +// + +#include "MsgDlg.h" + +#define JOYSTICK_NONE_ID 99999 +#define MAX_NUM_JOYSTICKS 16 + +typedef struct tagJoystickData { + int ID; + char name[1024]; + bool FF_capable; +} JoystickData; + +///////////////////////////////////////////////////////////////////////////// +// CJoystickTab dialog + +class CJoystickTab : public CPropertyPage +{ + DECLARE_DYNCREATE(CJoystickTab) + +// Construction +public: + CJoystickTab(); + ~CJoystickTab(); + + CMsgDlg m_MsgDlg; + +// Dialog Data + //{{AFX_DATA(CJoystickTab) + enum { IDD = IDD_PROPPAGE_JOYSTICK }; + CButton m_CHFlightEnabled; + CButton m_MousemanEnabled; + CComboBox m_joystick_list; + CButton m_ff_enabled; + //}}AFX_DATA + + void DetectSticks(); + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CJoystickTab) + public: + virtual void OnOK(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CJoystickTab) + virtual BOOL OnInitDialog(); + afx_msg void OnBtnCalibrate(); + afx_msg void OnBtnDetect(); + afx_msg void OnSelchangeJoystickList(); + afx_msg LRESULT OnCommandHelp(WPARAM wParam, LPARAM lParam); + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_JOYSTICKTAB_H__DB7960A2_20B5_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/KeyboardTab.cpp b/D3Launch/KeyboardTab.cpp new file mode 100644 index 00000000..6e5429fe --- /dev/null +++ b/D3Launch/KeyboardTab.cpp @@ -0,0 +1,262 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/KeyboardTab.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 11 6/09/99 2:46p Nate + * Minor changes for different builds + * + * 10 5/23/99 1:21a Nate + * Made FindFast Disabling default to "always" + * + * 9 5/22/99 1:39a Nate + * Added Find Fast support + * + * 8 5/07/99 11:24a Nate + * Added support for a launcher config file + * + * 7 5/05/99 11:38p Nate + * Disabled Language selection for US release builds + * + * 6 2/24/99 1:46p Nate + * Added multi-language support + * + * 5 10/13/98 3:03p Nate + * More fixes and changes. + * + * 4 9/22/98 3:33p Nate + * Added conditional compiling to help system (can toggle between HTML and + * standard windows help) + * + * 3 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 2 8/17/98 10:35a Nate + * Added Keyboard Type page to Setup + * + * $NoKeywords: $ + */ + +// KeyboardTab.cpp : implementation file +// + +#include "stdafx.h" +#include "afxpriv.h" +#include "afxext.h" +#include "d3launch.h" +#include "KeyboardTab.h" +#include "OS_Config.h" + +#include "LaunchNames.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define KEYBOARD_US "United States" +#define KEYBOARD_FRENCH "French" +#define KEYBOARD_GERMAN "German" + +///////////////////////////////////////////////////////////////////////////// +// CKeyboardTab property page + +IMPLEMENT_DYNCREATE(CKeyboardTab, CPropertyPage) + +CKeyboardTab::CKeyboardTab() : CPropertyPage(CKeyboardTab::IDD) +{ + //{{AFX_DATA_INIT(CKeyboardTab) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +CKeyboardTab::~CKeyboardTab() +{ +} + +void CKeyboardTab::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKeyboardTab) + DDX_Control(pDX, IDC_FINDFAST_CHECK, m_FindFastCheck); + DDX_Control(pDX, IDC_LANGUAGE_COMBO, m_LanguageCombo); + DDX_Control(pDX, IDC_COMMANDLINE_EDIT, m_CommandLineEdit); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CKeyboardTab, CPropertyPage) + //{{AFX_MSG_MAP(CKeyboardTab) + ON_MESSAGE(WM_COMMANDHELP,OnCommandHelp) + ON_WM_HELPINFO() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKeyboardTab message handlers + +BOOL CKeyboardTab::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + // Setup the language selection list + int lang_id; + + AddLangToList(IDS_LANG_ENGLISH,LANGUAGE_ENGLISH); +#ifdef USE_MULTI_LANGUAGES + AddLangToList(IDS_LANG_FRENCH,LANGUAGE_FRENCH); + AddLangToList(IDS_LANG_GERMAN,LANGUAGE_GERMAN); +#ifdef ENABLE_ITALIAN + AddLangToList(IDS_LANG_ITALIAN,LANGUAGE_ITALIAN); +#endif + AddLangToList(IDS_LANG_SPANISH,LANGUAGE_SPANISH); + lang_id = os_config_read_uint(szSectionName, "LanguageType", LANGUAGE_ENGLISH); +#else + lang_id = LANGUAGE_ENGLISH; +#endif + + SelectLangInList(lang_id); + + // Disable the language selection box + if(!LanguageSelectionEnabled) { + m_LanguageCombo.EnableWindow(FALSE); + } + + // Setup the keyboard type + char *keyboard_type = KEYBOARD_US; + keyboard_type = os_config_read_string(szSectionName, "KeyboardType", ""); + + if (!stricmp(keyboard_type, KEYBOARD_FRENCH)) + ((CButton *) GetDlgItem(IDC_FRENCH_KEYBOARD))->SetCheck(1); + else if (!stricmp(keyboard_type, KEYBOARD_GERMAN)) + ((CButton *) GetDlgItem(IDC_GERMAN_KEYBOARD))->SetCheck(1); + else { + ((CButton *) GetDlgItem(IDC_US_KEYBOARD))->SetCheck(1); + } + + // Set the FindFast checkbox + if(os_config_read_uint(szSectionName, "FindFastDisable",1)) + m_FindFastCheck.SetCheck(1); + else + m_FindFastCheck.SetCheck(0); + + // Read the command line + char *command_line; + command_line = os_config_read_string(szSectionName, "CmdLineOptions", ""); + m_CommandLineEdit.SetWindowText(command_line); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CKeyboardTab::OnOK() +{ + // Get the selected language + int prev_lang_id, lang_id; + lang_id=GetSelectedLangFromList(); + if(lang_id<0) lang_id=LANGUAGE_ENGLISH; + + prev_lang_id=os_config_read_uint(szSectionName, "LanguageType", LANGUAGE_ENGLISH); + if(prev_lang_id!=lang_id) NewLanguageSelected=TRUE; + os_config_write_uint(szSectionName, "LanguageType", lang_id); + + // Get the keyboard type + char *keyboard_type = KEYBOARD_US; + + if ( ((CButton *) GetDlgItem(IDC_FRENCH_KEYBOARD))->GetCheck() == 1 ) + keyboard_type = KEYBOARD_FRENCH; + else if ( ((CButton *) GetDlgItem(IDC_GERMAN_KEYBOARD))->GetCheck() == 1 ) + keyboard_type = KEYBOARD_GERMAN; + + os_config_write_string(szSectionName, "KeyboardType", keyboard_type); + + // save the findfast checkbox setting + if(m_FindFastCheck.GetCheck()) + os_config_write_uint(szSectionName, "FindFastDisable",1); + else + os_config_write_uint(szSectionName, "FindFastDisable",0); + + // write the command line + CString command_line; + m_CommandLineEdit.GetWindowText(command_line); + os_config_write_string(szSectionName, "CmdLineOptions", command_line.GetBuffer(0)); + + CPropertyPage::OnOK(); +} + +BOOL CKeyboardTab::OnHelpInfo(HELPINFO* pHelpInfo) +{ + // TODO: Add your message handler code here and/or call default +#ifdef USE_HTML_HELP_SYSTEM + CWaitCursor wc; + help_launch(KEYBOARDTAB_HELP); + return 1; +#else + return CPropertyPage::OnHelpInfo(pHelpInfo); +#endif +} + +// Display the html help file +afx_msg LRESULT CKeyboardTab::OnCommandHelp(WPARAM wParam, LPARAM lParam) +{ +#ifdef USE_HTML_HELP_SYSTEM + help_launch(KEYBOARDTAB_HELP); + return 1; +#else + return CPropertyPage::OnCommandHelp(wParam,lParam); +#endif +} + + +bool CKeyboardTab::AddLangToList(int stringID, int langID) +{ + int index; + CString lang_string; + + if(!lang_string.LoadString(stringID)) return FALSE; + + index=m_LanguageCombo.AddString(lang_string.GetBuffer(0)); + if(index<0) return FALSE; + + if(m_LanguageCombo.SetItemData(index,langID)==CB_ERR) return FALSE; + + return TRUE; +} + + +bool CKeyboardTab::SelectLangInList(int langID) +{ + int index, num_items; + + num_items=m_LanguageCombo.GetCount(); + for(index=0;index= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// KeyboardTab.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKeyboardTab dialog + +class CKeyboardTab : public CPropertyPage +{ + DECLARE_DYNCREATE(CKeyboardTab) + +// Construction +public: + CKeyboardTab(); + ~CKeyboardTab(); + + bool AddLangToList(int stringID, int langID); + bool SelectLangInList(int langID); + int GetSelectedLangFromList(void); + +// Dialog Data + //{{AFX_DATA(CKeyboardTab) + enum { IDD = IDD_PROPPAGE_KEYBOARD }; + CButton m_FindFastCheck; + CComboBox m_LanguageCombo; + CEdit m_CommandLineEdit; + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CKeyboardTab) + public: + virtual void OnOK(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CKeyboardTab) + virtual BOOL OnInitDialog(); + afx_msg LRESULT OnCommandHelp(WPARAM wParam, LPARAM lParam); + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_KEYBOARDTAB_H__9725ED00_35BA_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/Label.cpp b/D3Launch/Label.cpp new file mode 100644 index 00000000..3fa63d90 --- /dev/null +++ b/D3Launch/Label.cpp @@ -0,0 +1,271 @@ +// Label.cpp : implementation file +// + +#include "stdafx.h" +#include "Resource.h" +#include "Label.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLabel + +CLabel::CLabel() +{ + m_crText = GetSysColor(COLOR_WINDOWTEXT); + m_hBrush = ::CreateSolidBrush(GetSysColor(COLOR_3DFACE)); + + ::GetObject((HFONT)GetStockObject(DEFAULT_GUI_FONT),sizeof(m_lf),&m_lf); + + m_font.CreateFontIndirect(&m_lf); + m_bTimer = FALSE; + m_bState = FALSE; + m_bLink = TRUE; + m_hCursor = NULL; + m_Type = None; + + m_hwndBrush = ::CreateSolidBrush(GetSysColor(COLOR_3DFACE)); +} + + +CLabel::~CLabel() +{ + m_font.DeleteObject(); + ::DeleteObject(m_hBrush); +} + +CLabel& CLabel::SetText(const CString& strText) +{ + SetWindowText(strText); + return *this; +} + +CLabel& CLabel::SetTextColor(COLORREF crText) +{ + m_crText = crText; + RedrawWindow(); + return *this; +} + +CLabel& CLabel::SetFontBold(BOOL bBold) +{ + m_lf.lfWeight = bBold ? FW_BOLD : FW_NORMAL; + ReconstructFont(); + RedrawWindow(); + return *this; +} + +CLabel& CLabel::SetFontUnderline(BOOL bSet) +{ + m_lf.lfUnderline = bSet; + ReconstructFont(); + RedrawWindow(); + return *this; +} + +CLabel& CLabel::SetFontItalic(BOOL bSet) +{ + m_lf.lfItalic = bSet; + ReconstructFont(); + RedrawWindow(); + return *this; +} + +CLabel& CLabel::SetSunken(BOOL bSet) +{ + if (!bSet) + ModifyStyleEx(WS_EX_STATICEDGE,0,SWP_DRAWFRAME); + else + ModifyStyleEx(0,WS_EX_STATICEDGE,SWP_DRAWFRAME); + + return *this; +} + +CLabel& CLabel::SetBorder(BOOL bSet) +{ + if (!bSet) + ModifyStyle(WS_BORDER,0,SWP_DRAWFRAME); + else + ModifyStyle(0,WS_BORDER,SWP_DRAWFRAME); + + return *this; +} + +CLabel& CLabel::SetFontSize(int nSize) +{ + nSize*=-1; + m_lf.lfHeight = nSize; + ReconstructFont(); + RedrawWindow(); + return *this; +} + + +CLabel& CLabel::SetBkColor(COLORREF crBkgnd) +{ + if (m_hBrush) + ::DeleteObject(m_hBrush); + + m_hBrush = ::CreateSolidBrush(crBkgnd); + return *this; +} + +CLabel& CLabel::SetFontName(const CString& strFont) +{ + strcpy(m_lf.lfFaceName,strFont); + ReconstructFont(); + RedrawWindow(); + return *this; +} + + +BEGIN_MESSAGE_MAP(CLabel, CStatic) + //{{AFX_MSG_MAP(CLabel) + ON_WM_CTLCOLOR_REFLECT() + ON_WM_TIMER() + ON_WM_LBUTTONDOWN() + ON_WM_SETCURSOR() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLabel message handlers + +HBRUSH CLabel::CtlColor(CDC* pDC, UINT nCtlColor) +{ + // TODO: Change any attributes of the DC here + + // TODO: Return a non-NULL brush if the parent's handler should not be called + + if (CTLCOLOR_STATIC == nCtlColor) + { + pDC->SelectObject(&m_font); + pDC->SetTextColor(m_crText); + pDC->SetBkMode(TRANSPARENT); + } + + + if (m_Type == Background) + { + if (!m_bState) + return m_hwndBrush; + } + + return m_hBrush; +} + +void CLabel::ReconstructFont() +{ + m_font.DeleteObject(); + BOOL bCreated = m_font.CreateFontIndirect(&m_lf); + + ASSERT(bCreated); +} + + +CLabel& CLabel::FlashText(BOOL bActivate) +{ + if (m_bTimer) + { + SetWindowText(m_strText); + KillTimer(1); + } + + if (bActivate) + { + GetWindowText(m_strText); + m_bState = FALSE; + + m_bTimer = TRUE; + SetTimer(1,500,NULL); + m_Type = Text; + } + + return *this; +} + +CLabel& CLabel::FlashBackground(BOOL bActivate) +{ + + if (m_bTimer) + KillTimer(1); + + if (bActivate) + { + m_bState = FALSE; + + m_bTimer = TRUE; + SetTimer(1,500,NULL); + + m_Type = Background; + } + + return *this; +} + + +void CLabel::OnTimer(UINT nIDEvent) +{ + m_bState = !m_bState; + + switch (m_Type) + { + case Text: + if (m_bState) + SetWindowText(""); + else + SetWindowText(m_strText); + break; + + case Background: + InvalidateRect(NULL,FALSE); + UpdateWindow(); + break; + } + + CStatic::OnTimer(nIDEvent); +} + +CLabel& CLabel::SetLink(BOOL bLink) +{ + m_bLink = bLink; + + if (bLink) + ModifyStyle(0,SS_NOTIFY); + else + ModifyStyle(SS_NOTIFY,0); + + return *this; +} + +void CLabel::OnLButtonDown(UINT nFlags, CPoint point) +{ + CString strLink; + + GetWindowText(strLink); + ShellExecute(NULL,"open",strLink,NULL,NULL,SW_SHOWNORMAL); + + CStatic::OnLButtonDown(nFlags, point); +} + +BOOL CLabel::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) +{ + if (m_hCursor) + { + ::SetCursor(m_hCursor); + return TRUE; + } + + return CStatic::OnSetCursor(pWnd, nHitTest, message); +} + +CLabel& CLabel::SetLinkCursor(HCURSOR hCursor) +{ + m_hCursor = hCursor; + return *this; +} + diff --git a/D3Launch/Label.h b/D3Launch/Label.h new file mode 100644 index 00000000..cfa086df --- /dev/null +++ b/D3Launch/Label.h @@ -0,0 +1,77 @@ +#if !defined(AFX_LABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_) +#define AFX_LABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// Label.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLabel window +enum FlashType {None, Text, Background }; + +class CLabel : public CStatic +{ +// Construction +public: + CLabel(); + CLabel& SetBkColor(COLORREF crBkgnd); + CLabel& SetTextColor(COLORREF crText); + CLabel& SetText(const CString& strText); + CLabel& SetFontBold(BOOL bBold); + CLabel& SetFontName(const CString& strFont); + CLabel& SetFontUnderline(BOOL bSet); + CLabel& SetFontItalic(BOOL bSet); + CLabel& SetFontSize(int nSize); + CLabel& SetSunken(BOOL bSet); + CLabel& SetBorder(BOOL bSet); + CLabel& FlashText(BOOL bActivate); + CLabel& FlashBackground(BOOL bActivate); + CLabel& SetLink(BOOL bLink); + CLabel& SetLinkCursor(HCURSOR hCursor); + +// Attributes +public: +protected: + void ReconstructFont(); + COLORREF m_crText; + HBRUSH m_hBrush; + HBRUSH m_hwndBrush; + LOGFONT m_lf; + CFont m_font; + CString m_strText; + BOOL m_bState; + BOOL m_bTimer; + BOOL m_bLink; + FlashType m_Type; + HCURSOR m_hCursor; + // Operations +public: +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLabel) + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CLabel(); + + // Generated message map functions +protected: + //{{AFX_MSG(CLabel) + afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor); + afx_msg void OnTimer(UINT nIDEvent); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_) diff --git a/D3Launch/LaunchNames.h b/D3Launch/LaunchNames.h new file mode 100644 index 00000000..61f15b7b --- /dev/null +++ b/D3Launch/LaunchNames.h @@ -0,0 +1,312 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/LaunchNames.h $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 21 6/18/99 4:42p Nate + * Added non-LaserLock ROW version + * + * 20 6/09/99 2:46p Nate + * Minor changes for different builds + * + * 19 5/21/99 3:38p Nate + * Added changes for Rest of World release (new update directory path) + * + * 18 5/07/99 11:24a Nate + * Added support for a launcher config file + * + * 17 4/15/99 5:02p Nate + * Added localization support for the motd.txt file + * + * 16 4/15/99 12:03p Nate + * Added "Descent 3 Demo 2" build type + * + * 15 4/08/99 1:13p Nate + * Added Pentium III detection + * + * 14 3/29/99 3:14p Nate + * Added OEM_GENERIC + * + * 13 3/19/99 10:18a Nate + * Added OEM_GENERIC compile type + * + * 12 3/15/99 3:05p Nate + * Added readme viewer info + * + * 11 3/12/99 3:29p Nate + * Added more multi-language support + * + * 10 3/02/99 5:45p Nate + * Lots of little changes/fixes + * + * 9 2/26/99 12:50p Nate + * Changed OEM_Voodoo3 names + * + * 8 2/24/99 1:46p Nate + * Added multi-language support + * + * 7 2/17/99 2:23p Nate + * Added some OEM changes + * + * 6 11/06/98 3:17p Nate + * Added help created files + * + * 5 10/08/98 6:23p Nate + * Fixed a few bugs. + * + * 4 10/01/98 3:51p Nate + * Changed some file names and paths. + * + * 3 9/29/98 6:06p Nate + * Added UPDATED_VERSION_FNAME + * + * 2 8/24/98 7:06p Nate + * Added new AutoUpdate features, and fixed display glitches + * + * 1 8/19/98 10:47a Nate + * + * $NoKeywords: $ + */ + +#ifndef LAUNCHNAMES_H +#define LAUNCHNAMES_H + +// Localization defines +#define LANGUAGE_ENGLISH 0 +#define LANGUAGE_GERMAN 1 +#define LANGUAGE_SPANISH 2 +#define LANGUAGE_ITALIAN 3 +#define LANGUAGE_FRENCH 4 + +// Launcher's satellite resource DLL's +#define FRENCH_RESOURCE_DLL "language\\launcher\\D3Launch_FRN.dll" +#define GERMAN_RESOURCE_DLL "language\\launcher\\D3Launch_GER.dll" +#define ITALIAN_RESOURCE_DLL "language\\launcher\\D3Launch_ITN.dll" +#define SPANISH_RESOURCE_DLL "language\\launcher\\D3Launch_SPN.dll" + +// LauncherUpdater's satellite resource DLL's +#define LU_FRENCH_RES_DLL "language\\lnchupdr\\lnchupdr_FRN.dll" +#define LU_GERMAN_RES_DLL "language\\lnchupdr\\lnchupdr_GER.dll" +#define LU_ITALIAN_RES_DLL "language\\lnchupdr\\lnchupdr_ITN.dll" +#define LU_SPANISH_RES_DLL "language\\lnchupdr\\lnchupdr_SPN.dll" + +// Launcher help file info +#define LANGUAGE_HELP_PATH "language\\launcher\\hlp\\" + +// Language identification extensions +#define FRENCH_EXT "_FRN" +#define GERMAN_EXT "_GER" +#define ITALIAN_EXT "_ITN" +#define SPANISH_EXT "_SPN" + +// Launcher config file info +#define LANGUAGE_LAUNCHER_PATH "language\\launcher\\" +#define LAUNCHER_CONFIG_FNAME "d3launch.cfg" + +// Readme file info +#define LANGUAGE_README_PATH "language\\readmes\\" +#define README_CONFIG_FNAME "d3rmv.cfg" + +// The Mutex identification name for the D3 Launcher process +#define D3_LAUNCHER_MUTEX_NAME "D3LauncherMutexName" + +// The filename of .RTPatch DLL +#define PATCH_DLL_FNAME "patchw32.dll" + +// The CD volume names +#if defined(DEMO) +#define CD1_VOLUME_NAME "D3DEMO_1" +#define CD2_VOLUME_NAME "D3DEMO_2" +#elif defined(DEMO2) +#define CD1_VOLUME_NAME "D3DEMO_1" +#define CD2_VOLUME_NAME "D3DEMO_2" +#elif defined(OEM_GENERIC) +#define CD1_VOLUME_NAME "D3OEM_1" +#define CD2_VOLUME_NAME "D3OEM_2" +#elif defined(OEM_VOODOO3) +#define CD1_VOLUME_NAME "D3OEM_1" +#define CD2_VOLUME_NAME "D3OEM_2" +#elif defined(OEM_AUREAL2) +#define CD1_VOLUME_NAME "D3OEM_1" +#define CD2_VOLUME_NAME "D3OEM_2" +#elif defined(OEM_KATMAI) +#define CD1_VOLUME_NAME "D3OEM_1" +#define CD2_VOLUME_NAME "D3OEM_2" +#else +#define CD1_VOLUME_NAME "D3_1" +#define CD2_VOLUME_NAME "D3_2" +#endif + +// The filename of the ReadmeViewer +#define README_VIEWER_FNAME "ReadmeViewer.exe" + +// The filename of the Launcher executable (and help files) +#if defined(DEMO) +#define LAUNCHER_FNAME "Descent 3 Demo.exe" +#define HELP_HLP_FNAME "Descent 3 Demo.hlp" +#define HELP_CNT_FNAME "Descent 3 Demo.cnt" +#define HELP_GID_FNAME "DESCENT 3 DEMO.GID" +#define HELP_FTS_FNAME "DESCENT 3 DEMO.FTS" +#elif defined(DEMO2) +#define LAUNCHER_FNAME "Descent 3 Demo 2.exe" +#define HELP_HLP_FNAME "Descent 3 Demo 2.hlp" +#define HELP_CNT_FNAME "Descent 3 Demo 2.cnt" +#define HELP_GID_FNAME "DESCENT 3 DEMO 2.GID" +#define HELP_FTS_FNAME "DESCENT 3 DEMO 2.FTS" +#elif defined(OEM_GENERIC) +#define LAUNCHER_FNAME "Descent 3 SOL ASCENT.exe" +#define HELP_HLP_FNAME "Descent 3 SOL ASCENT.hlp" +#define HELP_CNT_FNAME "Descent 3 SOL ASCENT.cnt" +#define HELP_GID_FNAME "DESCENT 3 SOL ASCENT.GID" +#define HELP_FTS_FNAME "DESCENT 3 SOL ASCENT.FTS" +#elif (defined(OEM_VOODOO3) && !defined(USE_ALL_VIDEO_OPTIONS)) +#define LAUNCHER_FNAME "Descent 3 SOL ASCENT for Voodoo3.exe" +#define HELP_HLP_FNAME "Descent 3 SOL ASCENT for Voodoo3.hlp" +#define HELP_CNT_FNAME "Descent 3 SOL ASCENT for Voodoo3.cnt" +#define HELP_GID_FNAME "DESCENT 3 SOL ASCENT FOR VOODOO3.GID" +#define HELP_FTS_FNAME "DESCENT 3 SOL ASCENT FOR VOODOO3.FTS" +#elif (defined(OEM_VOODOO3) && defined(USE_ALL_VIDEO_OPTIONS)) +#define LAUNCHER_FNAME "Descent 3 SOL ASCENT.exe" +#define HELP_HLP_FNAME "Descent 3 SOL ASCENT.hlp" +#define HELP_CNT_FNAME "Descent 3 SOL ASCENT.cnt" +#define HELP_GID_FNAME "DESCENT 3 SOL ASCENT.GID" +#define HELP_FTS_FNAME "DESCENT 3 SOL ASCENT.FTS" +#elif defined(OEM_AUREAL2) +#define LAUNCHER_FNAME "Descent 3 SOL ASCENT for Aureal.exe" +#define HELP_HLP_FNAME "Descent 3 SOL ASCENT for Aureal.hlp" +#define HELP_CNT_FNAME "Descent 3 SOL ASCENT for Aureal.cnt" +#define HELP_GID_FNAME "DESCENT 3 SOL ASCENT FOR AUREAL.GID" +#define HELP_FTS_FNAME "DESCENT 3 SOL ASCENT FOR AUREAL.FTS" +#elif defined(OEM_KATMAI) +#define LAUNCHER_FNAME "Descent 3 SOL ASCENT for Pentium III.exe" +#define HELP_HLP_FNAME "Descent 3 SOL ASCENT for Pentium III.hlp" +#define HELP_CNT_FNAME "Descent 3 SOL ASCENT for Pentium III.cnt" +#define HELP_GID_FNAME "DESCENT 3 SOL ASCENT FOR PENTIUM III.GID" +#define HELP_FTS_FNAME "DESCENT 3 SOL ASCENT FOR PENTIUM III.FTS" +#else +#define LAUNCHER_FNAME "Descent 3.exe" +#define HELP_HLP_FNAME "Descent 3.hlp" +#define HELP_CNT_FNAME "Descent 3.cnt" +#define HELP_GID_FNAME "DESCENT 3.GID" +#define HELP_FTS_FNAME "DESCENT 3.FTS" +#endif + +// The filenames of the game executables +#define GAME_EXECUTABLE_FNAME "main.exe" +#define KATMAI_EXECUTABLE_FNAME "main_p3.exe" +#define GAME_EXECUTABLE_SWITCH "-launched" + +// The filename of the replacement Launcher executable +#define NEW_LAUNCHER_FNAME "launcher.new" + +// The filename of the replacement Launcher executable +#define LAUNCHER_PATCH_FNAME "launcher.rtp" + +// The filename of the Launcher replacement program +#define REPLACER_FNAME "lnchupdr.exe" + +// the local version, MOTD, sites, and patch filenames +#define VERSION_LOC_FNAME "version.nfo" +#define PATCH_LOC_FNAME "patch.rtp" +#define SITES_LOC_FNAME "sites.nfo" +#define MOTD_LOC_FNAME "motd.txt" + +// the Updated Version text file name +#define UPDATED_VERSION_FNAME "version.new" + +// the AutoUpdate source file paths (URLs) +#if defined(DEMO) +#define MOTD_PATH "http://www.outrage.com/update/descent3demo/motd.txt" +#define VERSION_PATH "http://www.outrage.com/update/descent3demo/version.nfo" +#elif defined(DEMO2) +#define MOTD_PATH "http://www.outrage.com/update/descent3demo2/motd.txt" +#define VERSION_PATH "http://www.outrage.com/update/descent3demo2/version.nfo" +#elif defined(OEM_GENERIC) +#define MOTD_PATH "http://www.outrage.com/update/descent3_oem/motd.txt" +#define VERSION_PATH "http://www.outrage.com/update/descent3_oem/version.nfo" +#elif defined(OEM_VOODOO3) +#define MOTD_PATH "http://www.outrage.com/update/descent3_oem_v3/motd.txt" +#define VERSION_PATH "http://www.outrage.com/update/descent3_oem_v3/version.nfo" +#elif defined(OEM_AUREAL2) +#define MOTD_PATH "http://www.outrage.com/update/descent3_oem_a2/motd.txt" +#define VERSION_PATH "http://www.outrage.com/update/descent3_oem_a2/version.nfo" +#elif defined(OEM_KATMAI) +#define MOTD_PATH "http://www.outrage.com/update/descent3_oem_km/motd.txt" +#define VERSION_PATH "http://www.outrage.com/update/descent3_oem_km/version.nfo" +#elif (defined(FULL_ROW_RELEASE) && !defined(ROW_NLL_RELEASE)) +#define MOTD_PATH "http://www.outrage.com/update/descent3_row/motd.txt" +#define VERSION_PATH "http://www.outrage.com/update/descent3_row/version.nfo" +#elif (defined(FULL_ROW_RELEASE) && defined(ROW_NLL_RELEASE)) +#define MOTD_PATH "http://www.outrage.com/update/descent3_row_nll/motd.txt" +#define VERSION_PATH "http://www.outrage.com/update/descent3_row_nll/version.nfo" +#elif defined(FULL_AUSSIE_RELEASE) +#define MOTD_PATH "http://www.outrage.com/update/descent3_aussie/motd.txt" +#define VERSION_PATH "http://www.outrage.com/update/descent3_aussie/version.nfo" +#else +#define MOTD_PATH "http://www.outrage.com/update/descent3/motd.txt" +#define VERSION_PATH "http://www.outrage.com/update/descent3/version.nfo" +#endif + +// Localized motd paths (for full release only) +#if (defined(FULL_ROW_RELEASE) && !defined(ROW_NLL_RELEASE)) +#define FRN_MOTD_PATH "http://www.outrage.com/update/descent3_row/motd_FRN.txt" +#define GER_MOTD_PATH "http://www.outrage.com/update/descent3_row/motd_GER.txt" +#define ITN_MOTD_PATH "http://www.outrage.com/update/descent3_row/motd_ITN.txt" +#define SPN_MOTD_PATH "http://www.outrage.com/update/descent3_row/motd_SPN.txt" +#elif (defined(FULL_ROW_RELEASE) && defined(ROW_NLL_RELEASE)) +#define FRN_MOTD_PATH "http://www.outrage.com/update/descent3_row_nll/motd_FRN.txt" +#define GER_MOTD_PATH "http://www.outrage.com/update/descent3_row_nll/motd_GER.txt" +#define ITN_MOTD_PATH "http://www.outrage.com/update/descent3_row_nll/motd_ITN.txt" +#define SPN_MOTD_PATH "http://www.outrage.com/update/descent3_row_nll/motd_SPN.txt" +#else +#define FRN_MOTD_PATH "http://www.outrage.com/update/descent3/motd_FRN.txt" +#define GER_MOTD_PATH "http://www.outrage.com/update/descent3/motd_GER.txt" +#define ITN_MOTD_PATH "http://www.outrage.com/update/descent3/motd_ITN.txt" +#define SPN_MOTD_PATH "http://www.outrage.com/update/descent3/motd_SPN.txt" +#endif + +// the Uninstallation path +#if defined(DEMO) +#define UNINSTALL_PATH "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Descent3Demo" +#elif defined(DEMO2) +#define UNINSTALL_PATH "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Descent3Demo2" +#elif defined(OEM_GENERIC) +#define UNINSTALL_PATH "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Descent3_OEM" +#elif defined(OEM_VOODOO3) +#define UNINSTALL_PATH "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Descent3_OEM_V3" +#elif defined(OEM_AUREAL2) +#define UNINSTALL_PATH "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Descent3_OEM_A2" +#elif defined(OEM_KATMAI) +#define UNINSTALL_PATH "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Descent3_OEM_KM" +#else +#define UNINSTALL_PATH "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Descent3" +#endif + +// Registry Value Names +#define REG_COMPANY_NAME "Outrage" + +#if defined(DEMO) +#define REG_APP_NAME "Descent3Demo"; +#elif defined(DEMO2) +#define REG_APP_NAME "Descent3Demo2"; +#elif defined(OEM_GENERIC) +#define REG_APP_NAME "Descent3_OEM"; +#elif defined(OEM_VOODOO3) +#define REG_APP_NAME "Descent3_OEM_V3"; +#elif defined(OEM_AUREAL2) +#define REG_APP_NAME "Descent3_OEM_A2"; +#elif defined(OEM_KATMAI) +#define REG_APP_NAME "Descent3_OEM_KM"; +#elif defined(GAMEGAUGE) +#define REG_APP_NAME "Descent3_GG"; +#else +#define REG_APP_NAME "Descent3"; +#endif + + +#endif /* LAUNCHNAMES_H */ \ No newline at end of file diff --git a/D3Launch/ListCtrlEx.cpp b/D3Launch/ListCtrlEx.cpp new file mode 100644 index 00000000..f3476533 --- /dev/null +++ b/D3Launch/ListCtrlEx.cpp @@ -0,0 +1,653 @@ +/******************************************************************************\ +* file : ListCtrlEx.cpp +* created: 1997.09.22 +* +* Zafir Anjum - Original author. +* Mark Findlay - IE4 fixes. +* Matthew Bells - Better TitleTips. +* +* description: +* A super CListControl. +*

features: +*

    +*
  • Title Tip item expantion +*
  • full row selection
    +* Note: this is also a feature in IE 4.0 with +* LVS_EX_FULLROWSELECT. +*
  • notifies parent selection has changed +*
  • supports column dragging (with IE4) which changes the column order +*
+* +\******************************************************************************/ +// ListCtrlEx.cpp : implementation of the CListCtrlEx class + +#include "stdafx.h" +#include +#include "ListCtrlEx.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CListCtrlEx + +IMPLEMENT_DYNCREATE(CListCtrlEx, CListCtrl) + +BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl) + //{{AFX_MSG_MAP(CListCtrlEx) + ON_WM_PAINT() + ON_WM_SETFOCUS() + ON_WM_KILLFOCUS() + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONDOWN() + ON_WM_KEYDOWN() + ON_WM_DESTROY() + //}}AFX_MSG_MAP + ON_MESSAGE(LVM_SETTEXTCOLOR, OnSetTextColor) + ON_MESSAGE(LVM_SETTEXTBKCOLOR, OnSetTextBkColor) + ON_MESSAGE(LVM_SETBKCOLOR, OnSetBkColor) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CListCtrlEx construction/destruction + +CListCtrlEx::CListCtrlEx() +{ + m_bFullRowSel = FALSE; + m_bClientWidthSel = TRUE; + + m_clrText = ::GetSysColor(COLOR_WINDOWTEXT); + m_clrTextBk = ::GetSysColor(COLOR_WINDOW); + m_clrBkgnd = ::GetSysColor(COLOR_WINDOW); +} + +CListCtrlEx::~CListCtrlEx() +{ +} + +// Make sure the control is owner drawn +BOOL CListCtrlEx::PreCreateWindow(CREATESTRUCT& cs) +{ + // default is report view and full row selection + cs.style &= ~LVS_TYPEMASK; + cs.style |= LVS_REPORT | LVS_OWNERDRAWFIXED; + m_bFullRowSel = TRUE; + + return(CListCtrl::PreCreateWindow(cs)); +} + +BOOL CListCtrlEx::SetFullRowSel(BOOL bFullRowSel) +{ + // no painting during change + LockWindowUpdate(); + + m_bFullRowSel = bFullRowSel; + + BOOL bRet; + + if (m_bFullRowSel) + bRet = ModifyStyle(0L, LVS_OWNERDRAWFIXED); + else + bRet = ModifyStyle(LVS_OWNERDRAWFIXED, 0L); + + // repaint window if we are not changing view type + if (bRet && (GetStyle() & LVS_TYPEMASK) == LVS_REPORT) + Invalidate(); + + // repaint changes + UnlockWindowUpdate(); + + return(bRet); +} + +BOOL CListCtrlEx::GetFullRowSel() +{ + return(m_bFullRowSel); +} + +///////////////////////////////////////////////////////////////////////////// +// CListCtrlEx drawing + +/* +* DrawItem() is called by the framework whenever an item needs to be drawn +* for owner drawn controls. +* Note: +*
    +*
  • LVS_SHOWSELALWAYS: non owner drawn controls show an item is +* highlighted when the control does not have focus with a different +* highlight color is (usually gray). This is not supported for +* this control. +*
+*/ + +void CListCtrlEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) +{ + CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); + int iSavedDC = pDC->SaveDC(); // Save DC state + + int iItem = lpDrawItemStruct->itemID; + + // Get item image and state info + LV_ITEM lvi; + lvi.mask = LVIF_IMAGE | LVIF_STATE; + lvi.iItem = iItem; + lvi.iSubItem = 0; + lvi.stateMask = 0xFFFF; // get all state flags + GetItem(&lvi); + + bool bHighlight = ( + (lvi.state & LVIS_DROPHILITED) || + ((lvi.state & LVIS_SELECTED) && ((GetFocus() == this) || (GetStyle() & LVS_SHOWSELALWAYS))) + ); + + // Get rectangles for drawing + CRect rcBounds; + CRect rcLabel; + CRect rcIcon; + GetItemRect(iItem, rcBounds, LVIR_BOUNDS); + GetItemRect(iItem, rcLabel, LVIR_LABEL); + GetItemRect(iItem, rcIcon, LVIR_ICON); + CRect rcItem(rcBounds); + + CString sLabel = GetItemText(iItem, 0); + + // Labels are offset by a certain amount + // This offset is related to the width of a space character + int offset = pDC->GetTextExtent(_T(" "), 1 ).cx*2; + + rcBounds.left = rcLabel.left; + CRect rcWnd; + GetClientRect(&rcWnd); + if(m_bClientWidthSel && rcBounds.rightSetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT)); + pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT)); + pDC->FillRect(rcBounds, &CBrush(::GetSysColor(COLOR_HIGHLIGHT))); + } + else + { + pDC->FillRect(rcBounds, &CBrush(m_clrTextBk)); + } + + // Set clip region + rcItem.right = rcItem.left + GetColumnWidth(0); +/* + CRgn rgn; + rgn.CreateRectRgnIndirect(&rcItem); + pDC->SelectClipRgn(&rgn); + rgn.DeleteObject(); +*/ + + // Draw state icon + if(lvi.state & LVIS_STATEIMAGEMASK) + { + int nImage = ((lvi.state & LVIS_STATEIMAGEMASK)>>12) - 1; + CImageList* pImageList = GetImageList(LVSIL_STATE); + if(pImageList) + { + pImageList->Draw(pDC, nImage, + CPoint(rcItem.left, rcItem.top), ILD_TRANSPARENT); + } + } + + // Draw normal and overlay icon + CImageList* pImageList = GetImageList(LVSIL_SMALL); + if(pImageList) + { + UINT nOvlImageMask = lvi.state & LVIS_OVERLAYMASK; + pImageList->Draw(pDC, lvi.iImage, + CPoint(rcIcon.left, rcIcon.top), + (bHighlight?ILD_BLEND50:0) | ILD_TRANSPARENT | nOvlImageMask ); + } + + // Draw item label - Column 0 + rcLabel.left += offset/2-1; + rcLabel.right -= offset; + pDC->DrawText(sLabel,-1,rcLabel,DT_LEFT | DT_SINGLELINE | DT_NOPREFIX + | DT_VCENTER | DT_END_ELLIPSIS); + + // Draw labels for remaining columns + LV_COLUMN lvc; + lvc.mask = LVCF_FMT | LVCF_WIDTH; + +/* +// set clip region + rcBounds.right = rcHighlight.right > rcBounds.right ? rcHighlight.right : + rcBounds.right; + rgn.CreateRectRgnIndirect(&rcBounds); + pDC->SelectClipRgn(&rgn); +*/ + for(int nColumn = 1; GetColumn(nColumn, &lvc); nColumn++) + { + rcItem.left = rcItem.right; + rcItem.right += lvc.cx; + + sLabel = GetItemText(iItem, nColumn); + + // Get the text justification + UINT nJustify = DT_LEFT; + switch(lvc.fmt & LVCFMT_JUSTIFYMASK) + { + case LVCFMT_RIGHT: + nJustify = DT_RIGHT; + break; + case LVCFMT_CENTER: + nJustify = DT_CENTER; + break; + default: + break; + } + + rcLabel = rcItem; + rcLabel.left += offset; + rcLabel.right -= offset; + + pDC->DrawText(sLabel, -1, rcLabel, + nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_END_ELLIPSIS); + } + + // draw focus rectangle if item has focus + if ((lvi.state & LVIS_FOCUSED) && (GetFocus() == this)) + pDC->DrawFocusRect(rcBounds); + + pDC->RestoreDC(iSavedDC); // Restore DC. +} + +///////////////////////////////////////////////////////////////////////////// +// CListCtrlEx diagnostics + +#ifdef _DEBUG + +void CListCtrlEx::Dump(CDumpContext& dc) const +{ + CListCtrl::Dump(dc); + + dc << "m_bFullRowSel = " << m_bFullRowSel; + dc << "\n"; +} + +#endif //_DEBUG + + +/** +* @param iRow [in] row of cell +* @param iColunm [in] column of cell +* @return Rectangle corresponding to the given cell. +*/ + +CRect CListCtrlEx::GetCellRect(int iRow, int iColumn)const +{ + // Make sure that the ListView is in LVS_REPORT + if((GetStyle() & LVS_TYPEMASK) != LVS_REPORT) + return CRect(0,0,0,0); + + // Get the number of columns + { + CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0); + int iColumnCount = pHeader->GetItemCount(); + assert(iColumn < iColumnCount); + } + + CRect rect; + GetItemRect(iRow, &rect, LVIR_BOUNDS); + // Now find the column + for(int colnum = 0; colnum < iColumn; colnum++) + { + rect.left += GetTrueColumnWidth(colnum); + } + + // Found the column + rect.right = rect.left + GetTrueColumnWidth(iColumn); + + RECT rectClient; + GetClientRect(&rectClient); + if(rect.right > rectClient.right) + rect.right = rectClient.right; + + return rect; +} + +/** +* @author Mark Findlay +*/ + +CString CListCtrlEx::GetTrueItemText(int row, int col)const +{ + // Get the header control + CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0); + _ASSERTE(pHeader); + + // get the current number of columns + int nCount = pHeader->GetItemCount(); + + // find the actual column requested. We will compare + // against hi.iOrder + for (int x=0; x< nCount; x++) + { + HD_ITEM hi = {0}; + hi.mask = HDI_ORDER; + + BOOL bRet = pHeader->GetItem(x,&hi); + _ASSERTE(bRet); + if (hi.iOrder == col) + { + // Found it, get the associated text + return GetItemText(row,x); + } + } + + _ASSERTE(FALSE); + return "We better never fall through to here!"; +} + +/** +* @author Mark Findlay +*/ + +int CListCtrlEx::GetTrueColumnWidth(int nCurrentPosition)const +{ + CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0); + _ASSERTE(pHeader); + + int nCount = pHeader->GetItemCount(); + + for (int x=0; x< nCount; x++) + { + HD_ITEM hi = {0}; + hi.mask = HDI_WIDTH | HDI_ORDER; + + BOOL bRet = pHeader->GetItem(x,&hi); + _ASSERTE(bRet); + if (hi.iOrder == nCurrentPosition) + return hi.cxy; + } + + _ASSERTE(FALSE); + return 0; // We would never fall through to here! +} + +void CListCtrlEx::HideTitleTip() +{ + m_titletip.ShowWindow(SW_HIDE); +} + +/** +* @param point [in] point in client coordinates +* @param iRow [out] row containing the point +* @param iColunm [out] column containing the point +* +* @author Matthew Bells +*/ + +bool CListCtrlEx::HitTestRowCol(CPoint& point, int& iRow, int& iColumn)const +{ + // Make sure that the ListView is in LVS_REPORT + if((GetStyle() & LVS_TYPEMASK) != LVS_REPORT) + return false; + + int iPosX = point.x; + iRow = HitTest(point); + + // Get the number of columns + CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0); + int iColumnCount = pHeader->GetItemCount(); + + for(iColumn = 0; iColumn < iColumnCount; ++iColumn) + { + iPosX -= GetTrueColumnWidth(iColumn); + if(iPosX < 0) + break; + } + if(iColumn == iColumnCount) + iColumn = -1; + + return (iRow != -1 && iColumn != -1); +} + +void CListCtrlEx::RepaintSelectedItems() +{ + CRect rcItem; + CRect rcLabel; + + // Invalidate focused item so it can repaint + + int iItem = GetNextItem(-1, LVNI_FOCUSED); + + if(iItem != -1) + { + GetItemRect(iItem, rcItem, LVIR_BOUNDS); + GetItemRect(iItem, rcLabel, LVIR_LABEL); + rcItem.left = rcLabel.left; + + InvalidateRect(rcItem, FALSE); + } + + // Invalidate selected items depending on LVS_SHOWSELALWAYS + + if(!(GetStyle() & LVS_SHOWSELALWAYS)) + { + for(iItem = GetNextItem(-1, LVNI_SELECTED); + iItem != -1; iItem = GetNextItem(iItem, LVNI_SELECTED)) + { + GetItemRect(iItem, rcItem, LVIR_BOUNDS); + GetItemRect(iItem, rcLabel, LVIR_LABEL); + rcItem.left = rcLabel.left; + + InvalidateRect(rcItem, FALSE); + } + } + + UpdateWindow(); +} + +///////////////////////////////////////////////////////////////////////////// +// CListCtrlEx message handlers + +void CListCtrlEx::OnDestroy() +{ + m_titletip.DestroyWindow(); + + CListCtrl::OnDestroy(); +} + +void CListCtrlEx::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + inherited::OnChar(nChar, nRepCnt, nFlags); + HideTitleTip(); + SendSelChangedNotification(); +} + +void CListCtrlEx::OnKillFocus(CWnd* pNewWnd) +{ + CListCtrl::OnKillFocus(pNewWnd); + + // This should be hidden no matter if another control is getting focus + // or the edit box. + HideTitleTip(); + + // this really still has focus if one of its chilren (ie. the edit box) + // has focus + if(pNewWnd != NULL && pNewWnd->GetParent() == this) + return; + + // repaint items that should change appearance + if(m_bFullRowSel && (GetStyle() & LVS_TYPEMASK) == LVS_REPORT) + RepaintSelectedItems(); +} + +void CListCtrlEx::OnLButtonDown(UINT nFlags, CPoint point) +{ + int iTest = GetKeyState(VK_LMENU); + // Shortcut to editing. + if((GetKeyState(VK_LMENU) & 0x8000) || (GetKeyState(VK_RMENU) & 0x8000)) + { + int iRow; + int iColumn; + if(HitTestRowCol(point, iRow, iColumn)) + { + SetFocus(); + PostMessage(LVM_EDITLABEL, (WPARAM)iRow, 0); + } + } + else + { + inherited::OnLButtonDown(nFlags, point); + ShowTitleTip(point); // Make sure TitleTip changes if needed. + SendSelChangedNotification(); + } +} + +void CListCtrlEx::OnMouseMove(UINT nFlags, CPoint point) +{ + if( nFlags == 0 ) + { + ShowTitleTip(point); // Make sure TitleTip changes if needed. + } + + CListCtrl::OnMouseMove(nFlags, point); +} + +/* +* When the regular list view control repaints an item, it repaints only the +* area occupied by defined columns. If the last column does not extend to the +* end of the client area, then the space to the right of the last column is +* not repainted. If we are highlighting the full row then this area also needs +* to be invalidated so that the code in DrawItem() can add or remove the +* highlighting from this area. +*/ + +void CListCtrlEx::OnPaint() +{ + // in full row select mode, we need to extend the clipping region + // so we can paint a selection all the way to the right + if (m_bClientWidthSel && + (GetStyle() & LVS_TYPEMASK) == LVS_REPORT && GetFullRowSel()) + { + CRect rcAllLabels; + GetItemRect(0, rcAllLabels, LVIR_BOUNDS); + + CRect rcClient; + GetClientRect(&rcClient); + if(rcAllLabels.right < rcClient.right) + { + // need to call BeginPaint (in CPaintDC c-tor) + // to get correct clipping rect + CPaintDC dc(this); + + CRect rcClip; + dc.GetClipBox(rcClip); + + rcClip.left = min(rcAllLabels.right-1, rcClip.left); + rcClip.right = rcClient.right; + + InvalidateRect(rcClip, FALSE); + // EndPaint will be called in CPaintDC d-tor + } + } + + CListCtrl::OnPaint(); +} + +LRESULT CListCtrlEx::OnSetBkColor(WPARAM wParam, LPARAM lParam) +{ + m_clrBkgnd = (COLORREF)lParam; + return(Default()); +} + +/* +* This is another step to mimic the default behaviour of the list view +* control. When the control loses focus, the focus rectangle around the +* selected (focus) item has to be removed. When the control gets back +* focus, then the focus rectangle has to be redrawn. Both these handlers +* call the RepaintSelectedItems() helper function. +*/ + +void CListCtrlEx::OnSetFocus(CWnd* pOldWnd) +{ + CListCtrl::OnSetFocus(pOldWnd); + + // check if we are getting focus from label edit box +// if(pOldWnd!=NULL && pOldWnd->GetParent()==this) +// return; + + // repaint items that should change appearance + if(m_bFullRowSel && (GetStyle() & LVS_TYPEMASK)==LVS_REPORT) + RepaintSelectedItems(); +} + +LRESULT CListCtrlEx::OnSetTextBkColor(WPARAM wParam, LPARAM lParam) +{ + m_clrTextBk = (COLORREF)lParam; + return(Default()); +} + +LRESULT CListCtrlEx::OnSetTextColor(WPARAM wParam, LPARAM lParam) +{ + m_clrText = (COLORREF)lParam; + return(Default()); +} + +void CListCtrlEx::PreSubclassWindow() +{ + CListCtrl::PreSubclassWindow(); + + m_titletip.Create(this); + m_titletip.SetBackground(CBrush(GetBkColor())); +} + +void CListCtrlEx::SendSelChangedNotification() +{ + NMHDR nmh; + nmh.hwndFrom = *this; + nmh.idFrom = GetDlgCtrlID(); + nmh.code = LVNU_SELCHANGED; + GetParent()->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmh); +} + +void CListCtrlEx::ShowTitleTip(CPoint point) +{ + int iRow; + int iCol; + + if(HitTestRowCol(point, iRow, iCol)) + { + CRect cellrect = GetCellRect(iRow, iCol); + // offset is equal to TextExtent of 2 space characters. + // Make sure you have the right font selected into the + // device context before calling GetTextExtent. + // You can save this value as a member variable. + // offset = pDC->GetTextExtent(_T(" "), 1 ).cx*2; + int offset = 6; + /*if(iCol == 0) + { + CRect rcLabel; + GetItemRect(iRow, &rcLabel, LVIR_LABEL ); + offset = rcLabel.left - cellrect.left + offset / 2 - 1; + }*/ + + if(iCol == 0) // TBD: test this with IE4 + cellrect.left -= 2; // Does it also move the first column??? + + cellrect.top--; + + if(GetItemState(iRow, LVIS_SELECTED)) + { + m_titletip.SetBkColor(::GetSysColor(COLOR_HIGHLIGHT)); + m_titletip.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT)); + } + else + { + m_titletip.SetBkColor(m_clrTextBk); + m_titletip.SetTextColor(m_clrText); + } + + m_titletip.Show(cellrect, GetTrueItemText(iRow, iCol), offset-1); + } +} diff --git a/D3Launch/ListCtrlEx.h b/D3Launch/ListCtrlEx.h new file mode 100644 index 00000000..67d231a7 --- /dev/null +++ b/D3Launch/ListCtrlEx.h @@ -0,0 +1,103 @@ +/******************************************************************************\ +* file : ListCtrl.h +* created: 1997.09.22 +* +* description: +* Implements a CListCtrl which can mark full rows. +\******************************************************************************/ + +#ifndef _CLISTCTRLEX_H_ +#define _CLISTCTRLEX_H_ + +#include "TitleTip.h" + +#define LVNU_SELCHANGED 0x1000 + +/** +* A super CListControl. +*

features: +*

    +*
  • Title Tip item expantion +*
  • full row selection +*
  • notifies parent selection has changed +*
  • +*
+*/ + +class CListCtrlEx : public CListCtrl +{ + typedef CListCtrl inherited; + + DECLARE_DYNCREATE(CListCtrlEx) + +// Construction +public: + CListCtrlEx(); + virtual ~CListCtrlEx(); + +// Attributes +protected: + BOOL m_bFullRowSel; + BOOL m_bClientWidthSel; + +public: + BOOL SetFullRowSel(BOOL bFillRowSel); + BOOL GetFullRowSel(); + +// Overrides +protected: + virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CListCtrlEx) + public: + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + protected: + virtual void PreSubclassWindow(); + //}}AFX_VIRTUAL + +// Implementation +public: +#ifdef _DEBUG + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + void RepaintSelectedItems(); + +// Implementation - list view colors + COLORREF m_clrText; + COLORREF m_clrTextBk; + COLORREF m_clrBkgnd; + CTitleTip m_titletip; + + afx_msg LRESULT OnSetTextColor(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnSetTextBkColor(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnSetBkColor(WPARAM wParam, LPARAM lParam); + + bool HitTestRowCol(CPoint& point, int& iRow, int& iColumn)const; + CRect GetCellRect(int iRow, int iColumn)const; + + int GetTrueColumnWidth(int nCurrentPosition)const; + CString GetTrueItemText(int row, int col)const; + void HideTitleTip(); + void SendSelChangedNotification(); + void ShowTitleTip(CPoint point); + + +// Generated message map functions +protected: + //{{AFX_MSG(CListCtrlEx) + afx_msg void OnPaint(); + afx_msg void OnSetFocus(CWnd* pOldWnd); + afx_msg void OnKillFocus(CWnd* pNewWnd); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnDestroy(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// +#endif diff --git a/D3Launch/MOTDDlg.cpp b/D3Launch/MOTDDlg.cpp new file mode 100644 index 00000000..a856e9ec --- /dev/null +++ b/D3Launch/MOTDDlg.cpp @@ -0,0 +1,94 @@ +// MOTDDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "d3launch.h" +#include "MOTDDlg.h" +#include "PsTypes.h" +#include "LaunchNames.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMOTDDlg dialog + + +CMOTDDlg::CMOTDDlg(CWnd* pParent /*=NULL*/) + : CDialog(CMOTDDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMOTDDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CMOTDDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMOTDDlg) + DDX_Control(pDX, IDC_LIST1, m_TextList); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CMOTDDlg, CDialog) + //{{AFX_MSG_MAP(CMOTDDlg) + ON_WM_SHOWWINDOW() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMOTDDlg message handlers + +BOOL CMOTDDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + m_TextList.ResetContent(); + + if(!ParseMOTDFile()) + return FALSE; + + m_TextList.SetTopIndex(0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +// Reads the message of the day text into the list box +BOOL CMOTDDlg::ParseMOTDFile(void) +{ + char filebuffer[PSPATHNAME_LEN+1]; + FILE *f; + + f = fopen(MOTD_LOC_FNAME, "rt"); + if(f == NULL){ + return FALSE; + } + + while (!feof(f)) { + fgets(filebuffer, PSPATHNAME_LEN, f); + if(strlen(filebuffer)>0 && filebuffer[strlen(filebuffer) - 1] == '\n') + filebuffer[strlen(filebuffer) - 1] = '\0'; + m_TextList.AddString(filebuffer); + } + fclose(f); + + return TRUE; +} + +void CMOTDDlg::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); + + // TODO: Add your message handler code here + //if(bShow==TRUE && nStatus==SW_PARENTOPENING) { + // OutputDebugString("Update dlg has opened\n"); + //} +} diff --git a/D3Launch/MOTDDlg.h b/D3Launch/MOTDDlg.h new file mode 100644 index 00000000..0fcb5cbe --- /dev/null +++ b/D3Launch/MOTDDlg.h @@ -0,0 +1,48 @@ +#if !defined(AFX_MOTDDLG_H__C5900F80_3B79_11D2_8CBD_00A0C96ED60D__INCLUDED_) +#define AFX_MOTDDLG_H__C5900F80_3B79_11D2_8CBD_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// MOTDDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CMOTDDlg dialog + +class CMOTDDlg : public CDialog +{ +// Construction +public: + CMOTDDlg(CWnd* pParent = NULL); // standard constructor + BOOL ParseMOTDFile(void); + +// Dialog Data + //{{AFX_DATA(CMOTDDlg) + enum { IDD = IDD_MOTD_DIALOG }; + CListBox m_TextList; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMOTDDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CMOTDDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MOTDDLG_H__C5900F80_3B79_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/MakeHelp.bat b/D3Launch/MakeHelp.bat new file mode 100644 index 00000000..02355103 --- /dev/null +++ b/D3Launch/MakeHelp.bat @@ -0,0 +1,39 @@ +@echo off +REM -- First make map file from Microsoft Visual C++ generated resource.h +echo // MAKEHELP.BAT generated Help Map file. Used by D3LAUNCH.HPJ. >"hlp\D3Launch.hm" +echo. >>"hlp\D3Launch.hm" +echo // Commands (ID_* and IDM_*) >>"hlp\D3Launch.hm" +makehm ID_,HID_,0x10000 IDM_,HIDM_,0x10000 resource.h >>"hlp\D3Launch.hm" +echo. >>"hlp\D3Launch.hm" +echo // Prompts (IDP_*) >>"hlp\D3Launch.hm" +makehm IDP_,HIDP_,0x30000 resource.h >>"hlp\D3Launch.hm" +echo. >>"hlp\D3Launch.hm" +echo // Resources (IDR_*) >>"hlp\D3Launch.hm" +makehm IDR_,HIDR_,0x20000 resource.h >>"hlp\D3Launch.hm" +echo. >>"hlp\D3Launch.hm" +echo // Dialogs (IDD_*) >>"hlp\D3Launch.hm" +makehm IDD_,HIDD_,0x20000 resource.h >>"hlp\D3Launch.hm" +echo. >>"hlp\D3Launch.hm" +echo // Frame Controls (IDW_*) >>"hlp\D3Launch.hm" +makehm IDW_,HIDW_,0x50000 resource.h >>"hlp\D3Launch.hm" +REM -- Make help for Project D3LAUNCH + + +echo Building Win32 Help files +start /wait "C:\Program Files\Help Workshop\hcw.exe" /C /E /M "hlp\D3Launch.hpj" +if errorlevel 1 goto :Error +if not exist "hlp\D3Launch.hlp" goto :Error +if not exist "hlp\D3Launch.cnt" goto :Error +echo. +if exist Debug\nul copy "hlp\D3Launch.hlp" Debug +if exist Debug\nul copy "hlp\D3Launch.cnt" Debug +if exist Release\nul copy "hlp\D3Launch.hlp" Release +if exist Release\nul copy "hlp\D3Launch.cnt" Release +echo. +goto :done + +:Error +echo hlp\D3Launch.hpj(1) : error: Problem encountered creating help file + +:done +echo. diff --git a/D3Launch/MessageWindowDlg.cpp b/D3Launch/MessageWindowDlg.cpp new file mode 100644 index 00000000..82df6e42 --- /dev/null +++ b/D3Launch/MessageWindowDlg.cpp @@ -0,0 +1,62 @@ +// MessageWindowDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "d3launch.h" +#include "MessageWindowDlg.h" +#include "UpdateDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +CMessageWindowDlg *message_window; + +///////////////////////////////////////////////////////////////////////////// +// CMessageWindowDlg dialog + + +CMessageWindowDlg::CMessageWindowDlg(CWnd* pParent /*=NULL*/) + : CDialog(CMessageWindowDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMessageWindowDlg) + m_WndMsgMain = _T(""); + m_WndMsgStatus = _T(""); + //}}AFX_DATA_INIT +} + + +void CMessageWindowDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMessageWindowDlg) + DDX_Text(pDX, IDC_WND_MSG_MAIN, m_WndMsgMain); + DDX_Text(pDX, IDC_WND_MSG_STATUS, m_WndMsgStatus); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CMessageWindowDlg, CDialog) + //{{AFX_MSG_MAP(CMessageWindowDlg) + ON_BN_CLICKED(IDC_BTN_CANCEL, OnBtnCancel) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMessageWindowDlg message handlers + + +void CMessageWindowDlg::OnBtnCancel() +{ + // TODO: Add your control notification handler code here + // Dim the button once pressed + HWND hwnd; + + GetDlgItem(IDC_BTN_CANCEL,&hwnd); + ::EnableWindow(hwnd,FALSE); + + // Mark cancel pressed global variable + CancelPressed=TRUE; +} diff --git a/D3Launch/MessageWindowDlg.h b/D3Launch/MessageWindowDlg.h new file mode 100644 index 00000000..fef0cbbe --- /dev/null +++ b/D3Launch/MessageWindowDlg.h @@ -0,0 +1,50 @@ +#if !defined(AFX_MESSAGEWINDOWDLG_H__65671E22_38F7_11D2_8CBD_00A0C96ED60D__INCLUDED_) +#define AFX_MESSAGEWINDOWDLG_H__65671E22_38F7_11D2_8CBD_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// MessageWindowDlg.h : header file +// + + +///////////////////////////////////////////////////////////////////////////// +// CMessageWindowDlg dialog + +class CMessageWindowDlg : public CDialog +{ +// Construction +public: + CMessageWindowDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CMessageWindowDlg) + enum { IDD = IDD_MESSAGE_WINDOW }; + CString m_WndMsgMain; + CString m_WndMsgStatus; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMessageWindowDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CMessageWindowDlg) + afx_msg void OnBtnCancel(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +extern CMessageWindowDlg *message_window; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MESSAGEWINDOWDLG_H__65671E22_38F7_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/MsgDlg.cpp b/D3Launch/MsgDlg.cpp new file mode 100644 index 00000000..faaf92af --- /dev/null +++ b/D3Launch/MsgDlg.cpp @@ -0,0 +1,45 @@ +// MsgDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "d3launch.h" +#include "MsgDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMsgDlg dialog + + +CMsgDlg::CMsgDlg(CWnd* pParent /*=NULL*/) + : CDialog(CMsgDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMsgDlg) + m_ScanningMsg = _T(""); + m_WaitMsg = _T(""); + //}}AFX_DATA_INIT +} + + +void CMsgDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMsgDlg) + DDX_Text(pDX, IDC_SCANNING_TEXT, m_ScanningMsg); + DDX_Text(pDX, IDC_WAIT_TEXT, m_WaitMsg); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CMsgDlg, CDialog) + //{{AFX_MSG_MAP(CMsgDlg) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMsgDlg message handlers diff --git a/D3Launch/MsgDlg.h b/D3Launch/MsgDlg.h new file mode 100644 index 00000000..3e6629da --- /dev/null +++ b/D3Launch/MsgDlg.h @@ -0,0 +1,47 @@ +#if !defined(AFX_MSGDLG_H__E14B21A1_5F9C_11D2_A4E0_00A0C96ED60D__INCLUDED_) +#define AFX_MSGDLG_H__E14B21A1_5F9C_11D2_A4E0_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MsgDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CMsgDlg dialog + +class CMsgDlg : public CDialog +{ +// Construction +public: + CMsgDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CMsgDlg) + enum { IDD = IDD_MSG_DLG }; + CString m_ScanningMsg; + CString m_WaitMsg; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMsgDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CMsgDlg) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MSGDLG_H__E14B21A1_5F9C_11D2_A4E0_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/NetworkTab.cpp b/D3Launch/NetworkTab.cpp new file mode 100644 index 00000000..8c89c0d4 --- /dev/null +++ b/D3Launch/NetworkTab.cpp @@ -0,0 +1,230 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/NetworkTab.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 7 5/19/99 12:29p Nate + * Fixed openGL crash, changed Network speed default, changed OpenGL + * detection to default to unchecked, and removed config file parsing from + * US version + * + * 6 9/22/98 3:33p Nate + * Added conditional compiling to help system (can toggle between HTML and + * standard windows help) + * + * 5 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 4 9/21/98 12:35p Nate + * Default network connection is now "Dialup" and default speed is "28K" + * + * 3 8/10/98 10:44a Nate + * Added Language selection support + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +// NetworkTab.cpp : implementation file +// + +#include "stdafx.h" +#include "afxpriv.h" +#include "afxext.h" +#include "D3Launch.h" +#include "NetworkTab.h" +#include "PsTypes.h" +#include "OS_Config.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define CONNECTION_DIALUP "Dialup" +#define CONNECTION_LAN "LAN" +#define CONNECTION_NONE "None" + +// defines for connection type +#define CONNECTION_SPEED_28K "28K" +#define CONNECTION_SPEED_33K "33K" +#define CONNECTION_SPEED_56K "56K" +#define CONNECTION_SPEED_SISDN "ISDN" +#define CONNECTION_SPEED_CABLE "Cable" +#define CONNECTION_SPEED_FAST "Fast" + +///////////////////////////////////////////////////////////////////////////// +// CNetworkTab property page + +IMPLEMENT_DYNCREATE(CNetworkTab, CPropertyPage) + +CNetworkTab::CNetworkTab() : CPropertyPage(CNetworkTab::IDD) +{ + //{{AFX_DATA_INIT(CNetworkTab) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +CNetworkTab::~CNetworkTab() +{ +} + +void CNetworkTab::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CNetworkTab) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CNetworkTab, CPropertyPage) + //{{AFX_MSG_MAP(CNetworkTab) + ON_BN_CLICKED(IDC_DIALUP, OnDialup) + ON_BN_CLICKED(IDC_LAN, OnLan) + ON_BN_CLICKED(IDC_NONE, OnNone) + ON_MESSAGE(WM_COMMANDHELP,OnCommandHelp) + ON_WM_HELPINFO() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CNetworkTab message handlers + +void CNetworkTab::OnOK() +{ + // TODO: Add your specialized code here and/or call the base class + char *internet_connection = CONNECTION_NONE; + char *connection_speed = CONNECTION_SPEED_28K; + + if ( ((CButton *) GetDlgItem(IDC_DIALUP))->GetCheck() == 1 ) + internet_connection = CONNECTION_DIALUP; + else if ( ((CButton *) GetDlgItem(IDC_LAN))->GetCheck() == 1 ) + internet_connection = CONNECTION_LAN; + + os_config_write_string(szSectionName, "NetworkConnection", internet_connection); + + // deal with the connection speed + if ( ((CButton *) GetDlgItem(IDC_FAST_CONNECTION))->GetCheck() == 1 ) + connection_speed = CONNECTION_SPEED_FAST; + else if ( ((CButton *) GetDlgItem(IDC_CABLE_CONNECTION))->GetCheck() == 1 ) + connection_speed = CONNECTION_SPEED_CABLE; + else if ( ((CButton *) GetDlgItem(IDC_SINGLE_ISDN_CONNECTION))->GetCheck() == 1 ) + connection_speed = CONNECTION_SPEED_SISDN; + else if ( ((CButton *) GetDlgItem(IDC_56K_CONNECTION))->GetCheck() == 1 ) + connection_speed = CONNECTION_SPEED_56K; + else if ( ((CButton *) GetDlgItem(IDC_33K_CONNECTION))->GetCheck() == 1 ) + connection_speed = CONNECTION_SPEED_33K; + else if ( ((CButton *) GetDlgItem(IDC_28K_CONNECTION))->GetCheck() == 1 ) + connection_speed = CONNECTION_SPEED_28K; + + os_config_write_string(szSectionName, "ConnectionSpeed", connection_speed); + + CPropertyPage::OnOK(); +} + +BOOL CNetworkTab::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + // TODO: Add extra initialization here + char *internet_connection, *connection_speed; + + internet_connection = os_config_read_string(szSectionName, "NetworkConnection", CONNECTION_DIALUP); + if (!stricmp(internet_connection, CONNECTION_DIALUP)) + ((CButton *) GetDlgItem(IDC_DIALUP))->SetCheck(1); + else if (!stricmp(internet_connection, CONNECTION_LAN)) + ((CButton *) GetDlgItem(IDC_LAN))->SetCheck(1); + else { + ((CButton *) GetDlgItem(IDC_NONE))->SetCheck(1); + EnableSpeedGroup(FALSE); + } + + // set up the connect speed radio buttons + connection_speed = os_config_read_string(szSectionName, "ConnectionSpeed", CONNECTION_SPEED_56K); + if ( !stricmp(connection_speed, CONNECTION_SPEED_FAST) ) + ((CButton *) GetDlgItem(IDC_FAST_CONNECTION))->SetCheck(1); + else if ( !stricmp(connection_speed, CONNECTION_SPEED_CABLE) ) + ((CButton *) GetDlgItem(IDC_CABLE_CONNECTION))->SetCheck(1); + else if ( !stricmp(connection_speed, CONNECTION_SPEED_SISDN) ) + ((CButton *) GetDlgItem(IDC_SINGLE_ISDN_CONNECTION))->SetCheck(1); + else if ( !stricmp(connection_speed, CONNECTION_SPEED_56K) ) + ((CButton *) GetDlgItem(IDC_56K_CONNECTION))->SetCheck(1); + else if ( !stricmp(connection_speed, CONNECTION_SPEED_33K) ) + ((CButton *) GetDlgItem(IDC_33K_CONNECTION))->SetCheck(1); + else + ((CButton *) GetDlgItem(IDC_28K_CONNECTION))->SetCheck(1); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CNetworkTab::EnableSpeedGroup(bool bEnable) +{ + HWND hwnd; + + GetDlgItem(IDC_28K_CONNECTION,&hwnd); + ::EnableWindow(hwnd,bEnable); + GetDlgItem(IDC_33K_CONNECTION,&hwnd); + ::EnableWindow(hwnd,bEnable); + GetDlgItem(IDC_56K_CONNECTION,&hwnd); + ::EnableWindow(hwnd,bEnable); + GetDlgItem(IDC_SINGLE_ISDN_CONNECTION,&hwnd); + ::EnableWindow(hwnd,bEnable); + GetDlgItem(IDC_CABLE_CONNECTION,&hwnd); + ::EnableWindow(hwnd,bEnable); + GetDlgItem(IDC_FAST_CONNECTION,&hwnd); + ::EnableWindow(hwnd,bEnable); + GetDlgItem(IDC_CONNECT_SPEED_GROUP,&hwnd); + ::EnableWindow(hwnd,bEnable); +} + +void CNetworkTab::OnDialup() +{ + // TODO: Add your control notification handler code here + EnableSpeedGroup(TRUE); +} + +void CNetworkTab::OnLan() +{ + // TODO: Add your control notification handler code here + EnableSpeedGroup(TRUE); +} + +void CNetworkTab::OnNone() +{ + // TODO: Add your control notification handler code here + EnableSpeedGroup(FALSE); +} + +BOOL CNetworkTab::OnHelpInfo(HELPINFO* pHelpInfo) +{ + // TODO: Add your message handler code here and/or call default +#ifdef USE_HTML_HELP_SYSTEM + CWaitCursor wc; + help_launch(NETWORKTAB_HELP); + return 1; +#else + return CPropertyPage::OnHelpInfo(pHelpInfo); +#endif +} + +// Display the html help file +afx_msg LRESULT CNetworkTab::OnCommandHelp(WPARAM wParam, LPARAM lParam) +{ +#ifdef USE_HTML_HELP_SYSTEM + help_launch(NETWORKTAB_HELP); + return 1; +#else + return CPropertyPage::OnCommandHelp(wParam,lParam); +#endif +} + diff --git a/D3Launch/NetworkTab.h b/D3Launch/NetworkTab.h new file mode 100644 index 00000000..beab43ae --- /dev/null +++ b/D3Launch/NetworkTab.h @@ -0,0 +1,77 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/NetworkTab.h $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 3 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +#if !defined(AFX_NETWORKTAB_H__FAB3D184_22D6_11D2_8CBD_00A0C96ED60D__INCLUDED_) +#define AFX_NETWORKTAB_H__FAB3D184_22D6_11D2_8CBD_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// NetworkTab.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CNetworkTab dialog + +class CNetworkTab : public CPropertyPage +{ + DECLARE_DYNCREATE(CNetworkTab) + +// Construction +public: + CNetworkTab(); + ~CNetworkTab(); + void EnableSpeedGroup(bool bEnable); + +// Dialog Data + //{{AFX_DATA(CNetworkTab) + enum { IDD = IDD_PROPPAGE_NETWORK }; + // NOTE - ClassWizard will add data members here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CNetworkTab) + public: + virtual void OnOK(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CNetworkTab) + virtual BOOL OnInitDialog(); + afx_msg void OnDialup(); + afx_msg void OnLan(); + afx_msg void OnNone(); + afx_msg LRESULT OnCommandHelp(WPARAM wParam, LPARAM lParam); + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_NETWORKTAB_H__FAB3D184_22D6_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/OS_Config.cpp b/D3Launch/OS_Config.cpp new file mode 100644 index 00000000..3e65aebf --- /dev/null +++ b/D3Launch/OS_Config.cpp @@ -0,0 +1,487 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/OS_Config.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 9 3/12/99 3:29p Nate + * Moved application registry names to LaunchNames.h + * + * 8 2/15/99 1:22p Kevin + * Changes for GameGauge + * + * 7 2/05/99 3:51p Nate + * Added conditional compilation directives for OEM support + * + * 6 9/23/98 11:21a Nate + * Added "demo" conditional compilation + * + * 5 9/22/98 3:34p Nate + * Changed registry key names to the "new ones" + * + * 4 9/21/98 11:58a Nate + * The section name is now NULL, so all launcher registry values will be + * written into the main Descent III key + * + * 3 8/10/98 10:44a Nate + * Added Language selection support + * + * 2 8/05/98 4:52p Nate + * Added registry reading and writing. + * + * 1 8/05/98 3:31p Nate + * Initial Version + * + * $NoKeywords: $ + */ + +#include "stdafx.h" +#include "PsTypes.h" +#include "D3Launch.h" + +#include "LaunchNames.h" + +// System Registry Functions + +char *szCompanyName = REG_COMPANY_NAME; +char *szAppName = REG_APP_NAME; +char *szSectionName = NULL; // Don't use a section name for the launcher + +// Removes a value from to the INI file. Passing +// name=NULL will delete the section. + +void os_config_remove( char *section, char *name ) +{ + HKEY hKey = NULL; + DWORD dwDisposition; + char keyname[1024]; + LONG lResult; + + if ( section ) { + sprintf( keyname, "Software\\%s\\%s\\%s", szCompanyName, szAppName, section ); + } else { + sprintf( keyname, "Software\\%s\\%s", szCompanyName, szAppName ); + } + + // remove the value + if ( !name ) { + if ( !section ) { + ////mprintf(( "Can't delete root key\n" )); + goto Cleanup; + } + lResult = RegDeleteKey( HKEY_LOCAL_MACHINE, keyname ); + if ( lResult != ERROR_SUCCESS ) { + ////mprintf(( "Error removing registry key '%s'\n", name )); + goto Cleanup; + } + } else { + lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE, // Where to add it + keyname, // name of key + NULL, // DWORD reserved + "", // Object class + REG_OPTION_NON_VOLATILE, // Save to disk + KEY_ALL_ACCESS, // Allows all changes + NULL, // Default security attributes + &hKey, // Location to store key + &dwDisposition ); // Location to store status of key + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error opening registry key '%s'\n", keyname )); + goto Cleanup; + } + + lResult = RegDeleteValue( hKey, name ); + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error removing registry value '%s'\n", name )); + goto Cleanup; + } + } + +Cleanup: + if ( hKey ) + RegCloseKey(hKey); +} + + +// Writes a string to the INI file. If value is NULL, +// removes the string. Writing a NULL value to a NULL name will delete +// the section. +void os_config_write_string( char *section, char *name, char *value ) +{ + HKEY hKey = NULL; + DWORD dwDisposition; + char keyname[1024]; + LONG lResult; + + + if ( section ) { + sprintf( keyname, "Software\\%s\\%s\\%s", szCompanyName, szAppName, section ); + } else { + sprintf( keyname, "Software\\%s\\%s", szCompanyName, szAppName ); + } + + lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE, // Where to add it + keyname, // name of key + NULL, // DWORD reserved + "", // Object class + REG_OPTION_NON_VOLATILE, // Save to disk + KEY_ALL_ACCESS, // Allows all changes + NULL, // Default security attributes + &hKey, // Location to store key + &dwDisposition ); // Location to store status of key + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error opening registry key '%s'\n", keyname )); + goto Cleanup; + } + + if ( !name ) { + //mprintf(( "No variable name passed\n" )); + goto Cleanup; + } + + lResult = RegSetValueEx( hKey, // Handle to key + name, // The values name + NULL, // DWORD reserved + REG_SZ, // null terminated string + (CONST BYTE *)value, // value to set + strlen(value) ); // How many bytes to set + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error writing registry key '%s'\n", name )); + goto Cleanup; + } + + +Cleanup: + if ( hKey ) + RegCloseKey(hKey); +} + +// same as previous function except we don't use the application name to build up the keyname +void os_config_write_string2( char *section, char *name, char *value ) +{ + HKEY hKey = NULL; + DWORD dwDisposition; + char keyname[1024]; + LONG lResult; + + + if ( section ) { + sprintf( keyname, "Software\\%s\\%s", szCompanyName, section ); + } else { + sprintf( keyname, "Software\\%s", szCompanyName ); + } + + lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE, // Where to add it + keyname, // name of key + NULL, // DWORD reserved + "", // Object class + REG_OPTION_NON_VOLATILE, // Save to disk + KEY_ALL_ACCESS, // Allows all changes + NULL, // Default security attributes + &hKey, // Location to store key + &dwDisposition ); // Location to store status of key + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error opening registry key '%s'\n", keyname )); + goto Cleanup; + } + + if ( !name ) { + //mprintf(( "No variable name passed\n" )); + goto Cleanup; + } + + lResult = RegSetValueEx( hKey, // Handle to key + name, // The values name + NULL, // DWORD reserved + REG_SZ, // null terminated string + (CONST BYTE *)value, // value to set + strlen(value) ); // How many bytes to set + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error writing registry key '%s'\n", name )); + goto Cleanup; + } + + +Cleanup: + if ( hKey ) + RegCloseKey(hKey); +} + +// Writes an unsigned int to the INI file. +void os_config_write_uint( char *section, char *name, uint value ) +{ + HKEY hKey = NULL; + DWORD dwDisposition; + char keyname[1024]; + LONG lResult; + + + if ( section ) { + sprintf( keyname, "Software\\%s\\%s\\%s", szCompanyName, szAppName, section ); + } else { + sprintf( keyname, "Software\\%s\\%s", szCompanyName, szAppName ); + } + + lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE, // Where to add it + keyname, // name of key + NULL, // DWORD reserved + "", // Object class + REG_OPTION_NON_VOLATILE, // Save to disk + KEY_ALL_ACCESS, // Allows all changes + NULL, // Default security attributes + &hKey, // Location to store key + &dwDisposition ); // Location to store status of key + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error opening registry key '%s'\n", keyname )); + goto Cleanup; + } + + if ( !name ) { + //mprintf(( "No variable name passed\n" )); + goto Cleanup; + } + + lResult = RegSetValueEx( hKey, // Handle to key + name, // The values name + NULL, // DWORD reserved + REG_DWORD, // null terminated string + (CONST BYTE *)&value, // value to set + 4 ); // How many bytes to set + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error writing registry key '%s'\n", name )); + goto Cleanup; + } + +Cleanup: + if ( hKey ) + RegCloseKey(hKey); + +} + + + + +// Reads a string from the INI file. If default is passed, +// and the string isn't found, returns ptr to default otherwise +// returns NULL; Copy the return value somewhere before +// calling os_read_string again, because it might reuse the +// same buffer. + +static char tmp_string_data[1024]; + +char * os_config_read_string( char *section, char *name, char *default_value ) +{ + HKEY hKey = NULL; + DWORD dwType, dwLen; + char keyname[1024]; + LONG lResult; + + + if ( section ) { + sprintf( keyname, "Software\\%s\\%s\\%s", szCompanyName, szAppName, section ); + } else { + sprintf( keyname, "Software\\%s\\%s", szCompanyName, szAppName ); + } + + lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, // Where it is + keyname, // name of key + NULL, // DWORD reserved + KEY_QUERY_VALUE, // Allows all changes + &hKey ); // Location to store key + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error opening registry key '%s'\n", keyname )); + goto Cleanup; + } + + if ( !name ) { + //mprintf(( "No variable name passed\n" )); + goto Cleanup; + } + + dwLen = 1024; + lResult = RegQueryValueEx( hKey, // Handle to key + name, // The values name + NULL, // DWORD reserved + &dwType, // What kind it is + (ubyte *)&tmp_string_data, // value to set + &dwLen ); // How many bytes to set + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error reading registry key '%s'\n", name )); + goto Cleanup; + } + + default_value = tmp_string_data; + +Cleanup: + if ( hKey ) + RegCloseKey(hKey); + + return default_value; +} + + +static char tmp_string_data_ex[1024]; + +char * os_config_read_string_ex( char *keyname, char *name, char *default_value ) +{ + HKEY hKey = NULL; + DWORD dwType, dwLen; + LONG lResult; + + lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, // Where it is + keyname, // name of key + NULL, // DWORD reserved + KEY_QUERY_VALUE, // Allows all changes + &hKey ); // Location to store key + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error opening registry key '%s'\n", keyname )); + goto Cleanup; + } + + if ( !name ) { + //mprintf(( "No variable name passed\n" )); + goto Cleanup; + } + + dwLen = 1024; + lResult = RegQueryValueEx( hKey, // Handle to key + name, // The values name + NULL, // DWORD reserved + &dwType, // What kind it is + (ubyte *)&tmp_string_data_ex, // value to set + &dwLen ); // How many bytes to set + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error reading registry key '%s'\n", name )); + goto Cleanup; + } + + default_value = tmp_string_data_ex; + +Cleanup: + if ( hKey ) + RegCloseKey(hKey); + + return default_value; +} + +char * os_config_read_string2( char *section, char *name, char *default_value ) +{ + HKEY hKey = NULL; + DWORD dwType, dwLen; + char keyname[1024]; + LONG lResult; + + + if ( section ) { + sprintf( keyname, "Software\\%s\\%s", szCompanyName, section ); + } else { + sprintf( keyname, "Software\\%s", szCompanyName ); + } + + lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, // Where it is + keyname, // name of key + NULL, // DWORD reserved + KEY_QUERY_VALUE, // Allows all changes + &hKey ); // Location to store key + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error opening registry key '%s'\n", keyname )); + goto Cleanup; + } + + if ( !name ) { + //mprintf(( "No variable name passed\n" )); + goto Cleanup; + } + + dwLen = 1024; + lResult = RegQueryValueEx( hKey, // Handle to key + name, // The values name + NULL, // DWORD reserved + &dwType, // What kind it is + (ubyte *)&tmp_string_data, // value to set + &dwLen ); // How many bytes to set + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error reading registry key '%s'\n", name )); + goto Cleanup; + } + + default_value = tmp_string_data; + +Cleanup: + if ( hKey ) + RegCloseKey(hKey); + + return default_value; +} + + +// Reads a string from the INI file. Default_value must +// be passed, and if 'name' isn't found, then returns default_value +uint os_config_read_uint( char *section, char *name, uint default_value ) +{ + HKEY hKey = NULL; + DWORD dwType, dwLen; + char keyname[1024]; + LONG lResult; + uint tmp_val; + + + if ( section ) { + sprintf( keyname, "Software\\%s\\%s\\%s", szCompanyName, szAppName, section ); + } else { + sprintf( keyname, "Software\\%s\\%s", szCompanyName, szAppName ); + } + + lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, // Where it is + keyname, // name of key + NULL, // DWORD reserved + KEY_QUERY_VALUE, // Allows all changes + &hKey ); // Location to store key + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error opening registry key '%s'\n", keyname )); + goto Cleanup; + } + + if ( !name ) { + //mprintf(( "No variable name passed\n" )); + goto Cleanup; + } + + dwLen = 4; + lResult = RegQueryValueEx( hKey, // Handle to key + name, // The values name + NULL, // DWORD reserved + &dwType, // What kind it is + (ubyte *)&tmp_val, // value to set + &dwLen ); // How many bytes to set + + if ( lResult != ERROR_SUCCESS ) { + //mprintf(( "Error reading registry key '%s'\n", name )); + goto Cleanup; + } + + default_value = tmp_val; + +Cleanup: + if ( hKey ) + RegCloseKey(hKey); + + return default_value; +} diff --git a/D3Launch/OS_Config.h b/D3Launch/OS_Config.h new file mode 100644 index 00000000..c8d1e49e --- /dev/null +++ b/D3Launch/OS_Config.h @@ -0,0 +1,41 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/OS_Config.h $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 4 9/09/98 12:24p Nate + * Added os_config_read_string_ex() prototype + * + * 3 8/10/98 10:44a Nate + * Added Language selection support + * + * 2 8/05/98 4:52p Nate + * Added registry reading and writing. + * + * 1 8/05/98 3:31p Nate + * Initial Version + * + * $NoKeywords: $ + */ + +// Header for System Registry functions + +#ifndef _OS_CONFIG_H +#define _OS_CONFIG_H + +#include "PsTypes.h" + +void os_config_write_string( char *section, char *name, char *value ); +char *os_config_read_string( char *section, char *name, char *default_value ); +uint os_config_read_uint( char *section, char *name, uint default_value ); +void os_config_write_uint( char *section, char *name, uint value ); +char *os_config_read_string_ex( char *keyname, char *name, char *default_value ); + +extern char *szSectionName; + +#endif //_OS_CONFIG_H \ No newline at end of file diff --git a/D3Launch/ReadMe.txt b/D3Launch/ReadMe.txt new file mode 100644 index 00000000..600c7334 --- /dev/null +++ b/D3Launch/ReadMe.txt @@ -0,0 +1,81 @@ +======================================================================== + MICROSOFT FOUNDATION CLASS LIBRARY : D3Launch +======================================================================== + + +AppWizard has created this D3Launch application for you. This application +not only demonstrates the basics of using the Microsoft Foundation classes +but is also a starting point for writing your application. + +This file contains a summary of what you will find in each of the files that +make up your D3Launch application. + +D3Launch.h + This is the main header file for the application. It includes other + project specific headers (including Resource.h) and declares the + CD3LaunchApp application class. + +D3Launch.cpp + This is the main application source file that contains the application + class CD3LaunchApp. + +D3Launch.rc + This is a listing of all of the Microsoft Windows resources that the + program uses. It includes the icons, bitmaps, and cursors that are stored + in the RES subdirectory. This file can be directly edited in Microsoft + Developer Studio. + +res\D3Launch.ico + This is an icon file, which is used as the application's icon. This + icon is included by the main resource file D3Launch.rc. + +res\D3Launch.rc2 + This file contains resources that are not edited by Microsoft + Developer Studio. You should place all resources not + editable by the resource editor in this file. + +D3Launch.clw + This file contains information used by ClassWizard to edit existing + classes or add new classes. ClassWizard also uses this file to store + information needed to create and edit message maps and dialog data + maps and to create prototype member functions. + + +///////////////////////////////////////////////////////////////////////////// + +AppWizard creates one dialog class: + +D3LaunchDlg.h, D3LaunchDlg.cpp - the dialog + These files contain your CD3LaunchDlg class. This class defines + the behavior of your application's main dialog. The dialog's + template is in D3Launch.rc, which can be edited in Microsoft + Developer Studio. + + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named D3Launch.pch and a precompiled types file named StdAfx.obj. + +Resource.h + This is the standard header file, which defines new resource IDs. + Microsoft Developer Studio reads and updates this file. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + +If your application uses MFC in a shared DLL, and your application is +in a language other than the operating system's current language, you +will need to copy the corresponding localized resources MFC40XXX.DLL +from the Microsoft Visual C++ CD-ROM onto the system or system32 directory, +and rename it to be MFCLOC.DLL. ("XXX" stands for the language abbreviation. +For example, MFC40DEU.DLL contains resources translated to German.) If you +don't do this, some of the UI elements of your application will remain in the +language of the operating system. + +///////////////////////////////////////////////////////////////////////////// diff --git a/D3Launch/SetupPropSheet.cpp b/D3Launch/SetupPropSheet.cpp new file mode 100644 index 00000000..042332cb --- /dev/null +++ b/D3Launch/SetupPropSheet.cpp @@ -0,0 +1,70 @@ +// SetupPropSheet.cpp : implementation file +// + +#include "stdafx.h" +#include "d3launch.h" +#include "SetupPropSheet.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CSetupPropSheet + +IMPLEMENT_DYNAMIC(CSetupPropSheet, CPropertySheet) + +CSetupPropSheet::CSetupPropSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage) + :CPropertySheet(nIDCaption, pParentWnd, iSelectPage) +{ +} + +CSetupPropSheet::CSetupPropSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage) + :CPropertySheet(pszCaption, pParentWnd, iSelectPage) +{ +} + +CSetupPropSheet::~CSetupPropSheet() +{ +} + + +BEGIN_MESSAGE_MAP(CSetupPropSheet, CPropertySheet) + //{{AFX_MSG_MAP(CSetupPropSheet) + // NOTE - the ClassWizard will add and remove mapping macros here. + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSetupPropSheet message handlers + +BOOL CSetupPropSheet::OnInitDialog() +{ + BOOL bResult = CPropertySheet::OnInitDialog(); + + // TODO: Add your specialized code here + HWND OK_btn = ::GetDlgItem(this->m_hWnd, IDOK); + if(OK_btn!=NULL) { + CString title; + title.LoadString(IDS_OK); + ::SetWindowText(OK_btn, title.GetBuffer(0)); + } + + HWND Cancel_btn = ::GetDlgItem(this->m_hWnd, IDCANCEL); + if(Cancel_btn!=NULL) { + CString title; + title.LoadString(IDS_CANCEL); + ::SetWindowText(Cancel_btn, title.GetBuffer(0)); + } + + HWND Help_btn = ::GetDlgItem(this->m_hWnd, IDHELP); + if(Help_btn!=NULL) { + CString title; + title.LoadString(IDS_HELP); + ::SetWindowText(Help_btn, title.GetBuffer(0)); + } + + return bResult; +} diff --git a/D3Launch/SetupPropSheet.h b/D3Launch/SetupPropSheet.h new file mode 100644 index 00000000..c692ee94 --- /dev/null +++ b/D3Launch/SetupPropSheet.h @@ -0,0 +1,52 @@ +#if !defined(AFX_SETUPPROPSHEET_H__00C45F60_1F5F_11D3_A4E1_00A0C96ED60D__INCLUDED_) +#define AFX_SETUPPROPSHEET_H__00C45F60_1F5F_11D3_A4E1_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// SetupPropSheet.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CSetupPropSheet + +class CSetupPropSheet : public CPropertySheet +{ + DECLARE_DYNAMIC(CSetupPropSheet) + +// Construction +public: + CSetupPropSheet(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0); + CSetupPropSheet(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSetupPropSheet) + public: + virtual BOOL OnInitDialog(); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CSetupPropSheet(); + + // Generated message map functions +protected: + //{{AFX_MSG(CSetupPropSheet) + // NOTE - the ClassWizard will add and remove member functions here. + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SETUPPROPSHEET_H__00C45F60_1F5F_11D3_A4E1_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/SiteSelectDlg.cpp b/D3Launch/SiteSelectDlg.cpp new file mode 100644 index 00000000..8525bbc9 --- /dev/null +++ b/D3Launch/SiteSelectDlg.cpp @@ -0,0 +1,234 @@ +// SiteSelectDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "d3launch.h" +#include "SiteSelectDlg.h" +#include "LaunchNames.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// Column header info +#define SITE_NAME_COLUMN 0 +#define SITE_ADDRESS_COLUMN 1 +#define SITE_LOCATION_COLUMN 2 + +#define SITE_NAME_COLUMN_WIDTH 0.3 +#define SITE_ADDRESS_COLUMN_WIDTH 0.4 +#define SITE_LOCATION_COLUMN_WIDTH 0.3 + + +///////////////////////////////////////////////////////////////////////////// +// CSiteSelectDlg dialog + + +CSiteSelectDlg::CSiteSelectDlg(CWnd* pParent /*=NULL*/) + : CDialog(CSiteSelectDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CSiteSelectDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CSiteSelectDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSiteSelectDlg) + DDX_Control(pDX, IDC_SITE_LIST, m_SiteList); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSiteSelectDlg, CDialog) + //{{AFX_MSG_MAP(CSiteSelectDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSiteSelectDlg message handlers + +void CSiteSelectDlg::OnOK() +{ + // TODO: Add extra validation here + int num_items, j, flags; + + // If no item is selected, return (user MUST select an item) + if(m_SiteList.GetSelectedCount()==0) { + LocalizedMessageBox(IDS_SITESELECTDLG_MUST_SELECT, IDS_SITESELECTDLG_SELECT_TITLE, MB_OK|MB_ICONEXCLAMATION); + return; + } + + // How many items in the control list? + num_items=m_SiteList.GetItemCount(); + + // scan the item list for the selected item + chosen_site=NO_SITE_CHOSEN; + j=0; + while(j0 && filebuffer[strlen(filebuffer) - 1] == '\n') + filebuffer[strlen(filebuffer) - 1] = '\0'; + + // if line is a comment, or empty, discard it + if(strlen(filebuffer)==0 || filebuffer[0]==SITE_FILE_COMMENT_CHAR) + continue; + + switch(field) { + case 0: + strcpy(site_entry.name,filebuffer); + break; + case 1: + strcpy(site_entry.location,filebuffer); + break; + case 2: + strcpy(site_entry.url,filebuffer); + break; + case 3: + strcpy(site_entry.path,filebuffer); + break; + } + + field++; + if(field==4) { + AddSiteEntry(&site_entry); + field=0; + } + } + fclose(f); + + return TRUE; +} + +// Adds an entry struct to the list array and the list control +BOOL CSiteSelectDlg::AddSiteEntry(SITE_ENTRY *entry) +{ + int index; + + // Check if too many sites have been read in + if(num_sites>=MAX_SITES) return FALSE; + + // Add the entry to the list control + index=m_SiteList.GetItemCount(); + if((index=m_SiteList.InsertItem(index,entry->name))==-1) + OutputDebugString("Didn't work!"); + + m_SiteList.SetItem(index,SITE_ADDRESS_COLUMN,LVIF_TEXT,entry->url,0,0,0,0); + m_SiteList.SetItem(index,SITE_LOCATION_COLUMN,LVIF_TEXT,entry->location,0,0,0,0); + + // Add the entry to the list array + strcpy(site_entries[num_sites].name,entry->name); + strcpy(site_entries[num_sites].location,entry->location); + strcpy(site_entries[num_sites].url,entry->url); + strcpy(site_entries[num_sites].path,entry->path); + num_sites++; + + return TRUE; +} + +void CSiteSelectDlg::LocalizedMessageBox(UINT msgID, UINT titleID, UINT type /*=MB_OK*/) +{ + CString msg, title; + + msg.LoadString(msgID); + title.LoadString(titleID); + MessageBox(msg,title,type); +} + diff --git a/D3Launch/SiteSelectDlg.h b/D3Launch/SiteSelectDlg.h new file mode 100644 index 00000000..b350050f --- /dev/null +++ b/D3Launch/SiteSelectDlg.h @@ -0,0 +1,73 @@ +#if !defined(AFX_SITESELECTDLG_H__65671E24_38F7_11D2_8CBD_00A0C96ED60D__INCLUDED_) +#define AFX_SITESELECTDLG_H__65671E24_38F7_11D2_8CBD_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// SiteSelectDlg.h : header file +// + +#include "PsTypes.h" +#include "ListCtrlEx.h" + +#define MAX_SITES 50 + +#define SITE_FILE_COMMENT_CHAR ';' + +// Structure for the site entries +typedef struct tagSITE_ENTRY { + char name[PSPATHNAME_LEN+1]; // The name/description of the site + char url[PSPATHNAME_LEN+1]; // Just the base http/ftp address + char location[PSPATHNAME_LEN+1]; // Where the site is located + char path[PSPATHNAME_LEN+1]; // The remote directory and patch filename +} SITE_ENTRY; + +#define NO_SITE_CHOSEN -1 + +///////////////////////////////////////////////////////////////////////////// +// CSiteSelectDlg dialog + +class CSiteSelectDlg : public CDialog +{ +// Construction +public: + CSiteSelectDlg(CWnd* pParent = NULL); // standard constructor + void SetColumnWidths(void); + BOOL AddSiteEntry(SITE_ENTRY *entry); + BOOL ParseSiteFile(void); + void LocalizedMessageBox(UINT msgID, UINT titleID, UINT type=MB_OK); + + SITE_ENTRY site_entries[MAX_SITES]; // array of site entries + int num_sites; // the number of sites in memory + int chosen_site; // the index of the chosen site + char download_path[PSPATHNAME_LEN*2+1]; // the full patch download path + +// Dialog Data + //{{AFX_DATA(CSiteSelectDlg) + enum { IDD = IDD_SITE_SELECTION_DIALOG }; + CListCtrlEx m_SiteList; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSiteSelectDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CSiteSelectDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SITESELECTDLG_H__65671E24_38F7_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/SpeedTab.cpp b/D3Launch/SpeedTab.cpp new file mode 100644 index 00000000..fba0b325 --- /dev/null +++ b/D3Launch/SpeedTab.cpp @@ -0,0 +1,641 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/SpeedTab.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 18 4/21/99 7:17p Nate + * Added "-nolightmaps" switch for LOW_DETAIL setting + * + * 17 4/08/99 1:13p Nate + * Added Pentium III detection + * + * 16 3/31/99 6:25p Nate + * Fixed potential bug in CPU speed reporting code + * + * 15 10/21/98 4:51p Nate + * Changed default to Medium; user only needs to visit the Speed tab now + * to get past the warning. + * + * 14 10/19/98 3:16p Nate + * Modified default detail level calculations + * + * 13 10/15/98 7:30p Nate + * + * 12 10/15/98 1:26p Nate + * Changed registry value name for the detail level + * + * 11 10/14/98 5:52p Nate + * More fixes + * + * 10 10/13/98 3:03p Nate + * More fixes and changes. + * + * 9 9/28/98 10:33a Nate + * Added flag for when list box selection changes (if flag is set when ok + * button is pressed, registry settings are changed to the selected + * default settings) + * + * 8 9/25/98 6:59p Nate + * Added code to write out detail level registry values. + * + * 7 9/22/98 3:33p Nate + * Added conditional compiling to help system (can toggle between HTML and + * standard windows help) + * + * 6 9/22/98 10:44a Nate + * Added prompt before changing default detail level. + * + * 5 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 4 9/02/98 9:48a Nate + * Fixed hardware accelerator display bug in the Speed Tab + * + * 3 8/10/98 10:44a Nate + * Added Language selection support + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +// SpeedTab.cpp : implementation file +// + +#include "stdafx.h" +#include "afxpriv.h" +#include "afxext.h" +#include "D3Launch.h" +#include "SpeedTab.h" +#include "PsTypes.h" +#include "VideoTab.h" +#include "3D_detect.h" +#include "OS_Config.h" + +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +typedef LONGLONG longlong; + + +///////////////////////////////////////////////////////////////////////////// +// CSpeedTab property page + +IMPLEMENT_DYNCREATE(CSpeedTab, CPropertyPage) + +CSpeedTab::CSpeedTab() : CPropertyPage(CSpeedTab::IDD) +{ + //{{AFX_DATA_INIT(CSpeedTab) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_WriteDetailValues=FALSE; +} + +CSpeedTab::~CSpeedTab() +{ +} + +void CSpeedTab::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSpeedTab) + DDX_Control(pDX, IDC_SPEED_LIST, m_speed_list); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSpeedTab, CPropertyPage) + //{{AFX_MSG_MAP(CSpeedTab) + ON_BN_CLICKED(IDC_BTN_SPEED_DETECT, OnBtnSpeedDetect) + ON_MESSAGE(WM_COMMANDHELP,OnCommandHelp) + ON_WM_HELPINFO() + ON_CBN_SELCHANGE(IDC_SPEED_LIST, OnSelchangeSpeedList) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSpeedTab message handlers + +void CSpeedTab::OnOK() +{ + // TODO: Add your specialized code here and/or call the base class + int cur_speed = m_speed_list.GetCurSel(); + + if ( (cur_speed < 0) || (cur_speed>CUSTOM_DETAIL)) { + cur_speed = 0; + } + + os_config_write_uint(szSectionName, "PredefDetailSetting", cur_speed ); + + // If the user has switched to a new default detail setting, + // then write out all the default detail levels to registry + if(m_WriteDetailValues) { + switch(cur_speed) { + case 0: + break; + case 1: + break; + case 2: + break; + case 3: + break; + } + m_WriteDetailValues=FALSE; + } + + // As long as they have viewed this page, they can get past the + // "set detail level" message when trying to play + DetailLevelConfigured=TRUE; + + CPropertyPage::OnOK(); +} + +BOOL CSpeedTab::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + // TODO: Add extra initialization here + // 0=low, 1=medium, 2=high, 3=very high + int cur_speed = os_config_read_uint(szSectionName, "PredefDetailSetting", MEDIUM_DETAIL ); + + if ( cur_speed < 0 ) + cur_speed = 0; + else if ( cur_speed > CUSTOM_DETAIL ) + cur_speed = VERY_HIGH_DETAIL; + + m_speed_list.ResetContent(); + + CString speed_type; + + speed_type.LoadString(IDS_SPEEDTAB_LOW); + m_speed_list.InsertString( LOW_DETAIL, speed_type ); + speed_type.LoadString(IDS_SPEEDTAB_MEDIUM); + m_speed_list.InsertString( MEDIUM_DETAIL, speed_type ); + speed_type.LoadString(IDS_SPEEDTAB_HIGH); + m_speed_list.InsertString( HIGH_DETAIL, speed_type ); + speed_type.LoadString(IDS_SPEEDTAB_VERY_HIGH); + m_speed_list.InsertString( VERY_HIGH_DETAIL, speed_type ); + + if(cur_speed==CUSTOM_DETAIL) { + speed_type.LoadString(IDS_SPEEDTAB_CUSTOM); + m_speed_list.InsertString( CUSTOM_DETAIL, speed_type ); + } + + m_speed_list.SetCurSel(cur_speed); + + m_WriteDetailValues=FALSE; + + // Blank out property entries so user can watch them fill up again + CString tmp_str; + char tmp[1024]; + HWND hwnd; + + tmp_str.LoadString(IDS_SPEEDTAB_NOT_DETECTED); + sprintf(tmp,"%s",tmp_str.GetBuffer(0)); + GetDlgItem( IDC_CPU_TYPE, &hwnd ); + ::SetWindowText( hwnd, tmp ); + GetDlgItem( IDC_CPU_SPEED, &hwnd ); + ::SetWindowText( hwnd, tmp ); + GetDlgItem( IDC_TOTAL_RAM, &hwnd ); + ::SetWindowText( hwnd, tmp ); + GetDlgItem( IDC_RAM_SPEED, &hwnd ); + ::SetWindowText( hwnd, tmp ); + GetDlgItem( IDC_VRAM_SPEED, &hwnd ); + ::SetWindowText( hwnd, tmp ); + GetDlgItem( IDC_3D_GRAPHICS_ACCELERATOR, &hwnd ); + ::SetWindowText( hwnd, tmp ); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +#define CPUID _asm _emit 0fh _asm _emit 0a2h +#define EMMS _asm _emit 0fh _asm _emit 077h +#define RTSC _asm _emit 0fh _asm _emit 031h + +DWORD ReadClocks() +{ + DWORD count; + + _asm { + RTSC + mov count, eax + } + return count; +} + + + +// ----------------------------------------------------------------------- +// Returns cpu type. +void detect_cpu(int *cpu, int *mmx, int *time_stamp_counter) +{ + BOOL retval = TRUE; + DWORD RegEDX; + DWORD RegEAX; + + // Set defaults + *cpu = 0; + *mmx = 0; + *time_stamp_counter = 0; + + + // jmp is not allowed in try + + _asm { + + // Check for prescence of + push eax + push ebx + push ecx + push edx + + pushfd // get extended flags + pop eax + mov ebx, eax // save current flags + xor eax, 200000h // toggle bit 21 + push eax // push new flags on stack + popfd // flags updated now in flags + pushfd // get extended flags + pop eax // store extended flags in eax + xor eax, ebx // if bit 21 r/w then eax <> 0 + je no_cpuid + + mov eax, 1 // setup CPUID to return features + + CPUID // code bytes = 0fh, 0a2h + + mov RegEAX, eax // family, etc returned in eax + mov RegEDX, edx // features returned in edx + jmp done_checking_cpuid + + +no_cpuid: + mov RegEAX, 4<<8 // family, etc returned in eax + mov RegEDX, 0 // features returned in edx + +done_checking_cpuid: + pop edx + pop ecx + pop ebx + pop eax + } + + + + //RegEAX . Bits 11:8 is family + *cpu = (RegEAX >>8) & 0xF; + + if ( *cpu < 5 ) { + *cpu = 4; // processor does not support CPUID + *mmx = 0; + } + + if (RegEDX & (1<<4) ) { // bit 4 is set for RTSC technology + *time_stamp_counter = 1; + } + + if (RegEDX & 0x800000) // bit 23 is set for MMX technology + { + + __try { + + _asm { + EMMS + } + + } // try executing an MMX instruction "emms" + + __except(EXCEPTION_EXECUTE_HANDLER) { retval = FALSE; } + + } else { + *mmx = 0; // processor supports CPUID but does not support MMX technology + return; + } + + + if ( retval == 0 ) { + // if retval == 0 here that means the processor has MMX technology but + // floating-point emulation is on; so MMX technology is unavailable + *mmx = 0; // processor supports CPUID but does not support MMX technology + return; + } + + *mmx = 1; // processor supports CPUID but does not support MMX technology +} + +// -------------------------------------------------------------------------- + +void CSpeedTab::OnBtnSpeedDetect() +{ + // TODO: Add your control notification handler code here + char tmp[1024]; + CString tmp_str; + HWND hwnd; + + // Set the wait cursor + CWaitCursor wc; + + // Blank out property entries so user can watch them fill up again + tmp_str.LoadString(IDS_SPEEDTAB_NOT_DETECTED); + sprintf(tmp,"%s",tmp_str.GetBuffer(0)); + GetDlgItem( IDC_CPU_TYPE, &hwnd ); + ::SetWindowText( hwnd, tmp ); + GetDlgItem( IDC_CPU_SPEED, &hwnd ); + ::SetWindowText( hwnd, tmp ); + GetDlgItem( IDC_TOTAL_RAM, &hwnd ); + ::SetWindowText( hwnd, tmp ); + GetDlgItem( IDC_RAM_SPEED, &hwnd ); + ::SetWindowText( hwnd, tmp ); + GetDlgItem( IDC_VRAM_SPEED, &hwnd ); + ::SetWindowText( hwnd, tmp ); + GetDlgItem( IDC_3D_GRAPHICS_ACCELERATOR, &hwnd ); + ::SetWindowText( hwnd, tmp ); + + + int cpu, mmx, timestamp_available; + detect_cpu( &cpu, &mmx, ×tamp_available ); + + switch( cpu ) { + case 3: + sprintf( tmp, "i386" ); + break; + case 4: + sprintf( tmp, "i486" ); + break; + case 5: + sprintf( tmp, "Pentium " ); + if ( mmx ) { + strcat( tmp, " w/ MMX" ); + } + break; + case 6: + if (SupportsKatmai()) { + sprintf( tmp, "Pentium III" ); + } else if ( mmx ) { + sprintf( tmp, "Pentium II w/ MMX" ); + } else { + sprintf( tmp, "Pentium Pro" ); + } + break; + default: + sprintf( tmp, "i%d86, MMX:%s", cpu, (mmx?"Yes":"No") ); + break; + } + + GetDlgItem( IDC_CPU_TYPE, &hwnd ); + ::SetWindowText( hwnd, tmp ); + + int NiceMhz = 0; + + + if ( timestamp_available ) { + DWORD t1; + DWORD c1, c2; + + do { + + t1 = timeGetTime() + 1000; + + c1 = ReadClocks(); + + while( timeGetTime() < t1 ) { + } + + c2 = ReadClocks(); + } while ( c2 < c1 ); // Retry if it rolled + + int Mhz = c2-c1; + + // Round to the nearest multiple of 16.66666666666667 + int factor = (Mhz+(16666667/2)) / 16666667; + + NiceMhz = (factor*16666667); + + NiceMhz /= 1000000; + + + } + + if ( NiceMhz < 1 ) { + sprintf( tmp, "Unknown\n" ); + } else { + sprintf( tmp, "%d MHz\n", NiceMhz ); + } + + GetDlgItem( IDC_CPU_SPEED, &hwnd ); + ::SetWindowText( hwnd, tmp ); + + + MEMORYSTATUS ms; + ms.dwLength = sizeof(MEMORYSTATUS); + GlobalMemoryStatus(&ms); + DWORD descent3_total_ram = (ms.dwTotalPhys+(4194304/2))/(4194304); + descent3_total_ram *= 4; + sprintf( tmp, "%d MB", descent3_total_ram ); + GetDlgItem( IDC_TOTAL_RAM, &hwnd ); + ::SetWindowText( hwnd, tmp ); + + + // Test memory READ speed. + int *array1, *array2; + + array1 = new int[1024*1024]; + array2 = new int[1024*1024]; + + longlong ct1, ct2, freq; + + QueryPerformanceCounter( (LARGE_INTEGER *)&ct1 ); + + int count=0; + + DWORD t1 = timeGetTime() + 1000; + + while( timeGetTime() < t1 ) { + _asm { + push esi + push edi + push ecx + mov esi, array2 + mov edi, array1 + mov ecx, (1024*1024/16) + rep movsd + pop ecx + pop edi + pop esi + } + count++; + } + + QueryPerformanceCounter( (LARGE_INTEGER *)&ct2 ); + QueryPerformanceFrequency( (LARGE_INTEGER *)&freq ); + + delete(array1); + delete(array2); + + longlong deltat = (ct2-ct1)/count; + + int speed = int(freq/deltat); + + // Round to nearest 10 MB/s +// speed = (speed+5)/10; +// speed = speed*10; + + sprintf( tmp, "%d MB/s", speed ); + GetDlgItem( IDC_RAM_SPEED, &hwnd ); + ::SetWindowText( hwnd, tmp ); + + + HDC hScreenDC = ::GetDC(NULL); + HDC hMemDC = CreateCompatibleDC(hScreenDC); + + int w, h; + w = GetDeviceCaps(hScreenDC,HORZRES); + h = GetDeviceCaps(hScreenDC,VERTRES); + + HBITMAP hBmp = CreateCompatibleBitmap( hScreenDC, w, h*4 ); + if (hBmp && hScreenDC && hMemDC ) { + SelectObject( hMemDC, hBmp ); + + BitBlt( hMemDC, 0, 0, w, h, hScreenDC, 0, 0, SRCCOPY ); + + QueryPerformanceCounter( (LARGE_INTEGER *)&ct1 ); + BitBlt( hScreenDC, 0, 0, w, h, hMemDC, 0, 0, SRCCOPY ); + GdiFlush(); + QueryPerformanceCounter( (LARGE_INTEGER *)&ct2 ); + + QueryPerformanceFrequency( (LARGE_INTEGER *)&freq ); + + deltat = ct2-ct1; + + //longlong speed = (longlong(300)*freq)/(deltat*longlong(1024)); + + int bpp = GetDeviceCaps(hScreenDC,BITSPIXEL); + int bpp1 = (bpp+7)/8; + + longlong vram_speed = freq; + vram_speed /= (longlong)deltat; + vram_speed *= (longlong)(w*h*bpp1); + vram_speed /= (longlong)(1024*1024); + + speed = int(vram_speed); + + sprintf( tmp, "%d MB/s\n", speed ); + GetDlgItem( IDC_VRAM_SPEED, &hwnd ); + ::SetWindowText( hwnd, tmp ); + + DeleteObject(hBmp); + } else { + speed = 0; + sprintf( tmp, "%d MB/s\n", speed ); + GetDlgItem( IDC_VRAM_SPEED, &hwnd ); + ::SetWindowText( hwnd, "unknown" ); + } + + ::DeleteDC( hMemDC ); + ::DeleteDC( hScreenDC ); + + + int current_card = 0; + int graphics_accelerator = RENDERER_NONE; + GetDlgItem( IDC_3D_GRAPHICS_ACCELERATOR, &hwnd ); + + // If the video tab has been initialized, get card from there + if ( CurrentVideoTab && Num_cards !=0 ) { + current_card = CurrentVideoTab->GetCurrentCard(); + ::SetWindowText( hwnd, GetFullName(&Cards[current_card]) ); + graphics_accelerator=Cards[current_card].renderer_type; + } + else { // otherwise, get it from the registry + RendererType renderer_id = (RendererType)os_config_read_uint(NULL, "PreferredRenderer", RENDERER_NONE); + char *card_name = os_config_read_string(szSectionName, "RenderingDeviceName", "" ); + card3d temp_card; + temp_card.renderer_type=renderer_id; + strcpy(temp_card.name,card_name); + ::SetWindowText( hwnd, GetFullName(&temp_card) ); + graphics_accelerator=temp_card.renderer_type; + } + + // Calculate default detail level based on CPU speed, and then weight it on + // System RAM and whether or not they are using Glide + int recommended_detail_level; + + // calculate setting based roughly on CPU speed + if ( NiceMhz <= 300 ) { + recommended_detail_level = LOW_DETAIL; + } else if ( NiceMhz <= 400 ) { + recommended_detail_level = MEDIUM_DETAIL; + } else if ( NiceMhz <= 500 ) { + recommended_detail_level = HIGH_DETAIL; + } else { + recommended_detail_level = VERY_HIGH_DETAIL; + } + + // weight the setting if user has ample supply of RAM + if ( descent3_total_ram >= 64 ) + recommended_detail_level++; + + // weight the setting if user has Glide selected as API + if ( graphics_accelerator == RENDERER_GLIDE ) + recommended_detail_level++; + + // Make sure detail level is capped at the highest setting + if ( recommended_detail_level > VERY_HIGH_DETAIL ) + recommended_detail_level = VERY_HIGH_DETAIL; + + // Ask the user if he/she wants detail level changed + if(m_speed_list.GetCurSel()!=recommended_detail_level) { + CString speed_prompt, speed_title; + speed_prompt.LoadString(IDS_SPEEDTAB_SPEED_PROMPT); + speed_title.LoadString(IDS_SPEEDTAB_SPEED_TITLE); + if(MessageBox(speed_prompt,speed_title,MB_YESNO|MB_ICONQUESTION)==IDNO) + return; + } + + // Set the new detail level + m_speed_list.SetCurSel(recommended_detail_level); + DetailLevelConfigured=TRUE; + m_WriteDetailValues=TRUE; +} + +BOOL CSpeedTab::OnHelpInfo(HELPINFO* pHelpInfo) +{ + // TODO: Add your message handler code here and/or call default + +#ifdef USE_HTML_HELP_SYSTEM + CWaitCursor wc; + help_launch(SPEEDTAB_HELP); + return 1; +#else + return CPropertyPage::OnHelpInfo(pHelpInfo); +#endif +} + +// Display the html help file +afx_msg LRESULT CSpeedTab::OnCommandHelp(WPARAM wParam, LPARAM lParam) +{ +#ifdef USE_HTML_HELP_SYSTEM + help_launch(SPEEDTAB_HELP); + return 1; +#else + return CPropertyPage::OnCommandHelp(wParam,lParam); +#endif +} + + +void CSpeedTab::OnSelchangeSpeedList() +{ + // TODO: Add your control notification handler code here + m_WriteDetailValues=TRUE; +} diff --git a/D3Launch/SpeedTab.h b/D3Launch/SpeedTab.h new file mode 100644 index 00000000..94b7d4bc --- /dev/null +++ b/D3Launch/SpeedTab.h @@ -0,0 +1,93 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/SpeedTab.h $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 6 4/21/99 7:17p Nate + * Added "-nolightmaps" switch for LOW_DETAIL setting + * + * 5 9/28/98 10:49a Nate + * Added flag for when list box selection changes (if flag is set when ok + * button is pressed, registry settings are changed to the selected + * default settings) + * + * 4 9/25/98 6:59p Nate + * Added code to write out detail level registry values. + * + * 3 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +#if !defined(AFX_SPEEDTAB_H__FAB3D183_22D6_11D2_8CBD_00A0C96ED60D__INCLUDED_) +#define AFX_SPEEDTAB_H__FAB3D183_22D6_11D2_8CBD_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// SpeedTab.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CSpeedTab dialog + +#define LOW_DETAIL 0 +#define MEDIUM_DETAIL 1 +#define HIGH_DETAIL 2 +#define VERY_HIGH_DETAIL 3 +#define CUSTOM_DETAIL 4 + +class CSpeedTab : public CPropertyPage +{ + DECLARE_DYNCREATE(CSpeedTab) + +// Construction +public: + CSpeedTab(); + ~CSpeedTab(); + + bool m_WriteDetailValues; + +// Dialog Data + //{{AFX_DATA(CSpeedTab) + enum { IDD = IDD_PROPPAGE_SPEED }; + CComboBox m_speed_list; + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CSpeedTab) + public: + virtual void OnOK(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CSpeedTab) + virtual BOOL OnInitDialog(); + afx_msg void OnBtnSpeedDetect(); + afx_msg LRESULT OnCommandHelp(WPARAM wParam, LPARAM lParam); + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); + afx_msg void OnSelchangeSpeedList(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SPEEDTAB_H__FAB3D183_22D6_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/StdAfx.cpp b/D3Launch/StdAfx.cpp new file mode 100644 index 00000000..911fc17c --- /dev/null +++ b/D3Launch/StdAfx.cpp @@ -0,0 +1,6 @@ +// stdafx.cpp : source file that includes just the standard includes +// D3Launch.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + diff --git a/D3Launch/StdAfx.h b/D3Launch/StdAfx.h new file mode 100644 index 00000000..85b13d79 --- /dev/null +++ b/D3Launch/StdAfx.h @@ -0,0 +1,26 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__9149CF3C_207D_11D2_8CBD_00A0C96ED60D__INCLUDED_) +#define AFX_STDAFX_H__9149CF3C_207D_11D2_8CBD_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +//#include // MFC OLE automation classes +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__9149CF3C_207D_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/TitleTip.cpp b/D3Launch/TitleTip.cpp new file mode 100644 index 00000000..fc4aa54b --- /dev/null +++ b/D3Launch/TitleTip.cpp @@ -0,0 +1,268 @@ +//////////////////////////////////////////////////////////////////////////// +// TitleTip.cpp : implementation file +// + +#include "stdafx.h" +#include "TitleTip.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CTitleTip + +CTitleTip::CTitleTip() +{ + m_iHorzSpace = 2; + m_brshBackground = (HBRUSH)0; + + m_clrBackground = ::GetSysColor(COLOR_HIGHLIGHT); + m_clrText = ::GetSysColor(COLOR_HIGHLIGHTTEXT); + + RegisterWindowClass(); // Register window class if not already registered. +} + +CTitleTip::~CTitleTip() +{ +} + +// static +void +CTitleTip::RegisterWindowClass() +{ + WNDCLASS wndcls; + HINSTANCE hInst = AfxGetInstanceHandle(); + if(!(::GetClassInfo(hInst, TITLETIP_CLASSNAME, &wndcls))) + { + // otherwise we need to register a new class + wndcls.style = CS_SAVEBITS | CS_DBLCLKS; + wndcls.lpfnWndProc = ::DefWindowProc; + wndcls.cbClsExtra = wndcls.cbWndExtra = 0; + wndcls.hInstance = hInst; + wndcls.hIcon = NULL; + wndcls.hCursor = LoadCursor( hInst, IDC_ARROW ); + wndcls.hbrBackground = (HBRUSH)(COLOR_INFOBK + 1); + wndcls.lpszMenuName = NULL; + wndcls.lpszClassName = TITLETIP_CLASSNAME; + if (!AfxRegisterClass(&wndcls)) + AfxThrowResourceException(); + } +} + + +BEGIN_MESSAGE_MAP(CTitleTip, CWnd) + //{{AFX_MSG_MAP(CTitleTip) + ON_WM_MOUSEMOVE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +void CTitleTip::SetBackground(HBRUSH brshBackground) +{ + m_brshBackground = brshBackground; +} + +void CTitleTip::SetBkColor(COLORREF crColor) +{ + m_clrBackground = crColor; +} + +void CTitleTip::SetTextColor(COLORREF crColor) +{ + m_clrText = crColor; +} + +///////////////////////////////////////////////////////////////////////////// +// CTitleTip message handlers + +/* +* styles: +*
    +*
  • WS_BORDER: draws a border around the titletip window +*
  • WS_POPUP: needed so that the TitleTip window is able to extend +* beyond the boundary of the control +*
  • WS_EX_TOOLWINDOW: stops the window from appearing in the task bar +*
  • WS_EX_TOPMOST: ensures the titletip is visible +*
  • COLOR_INFOBK: the same color used by ToolTip +*
+*/ + +BOOL CTitleTip::Create(CWnd * pParentWnd) +{ + ASSERT_VALID(pParentWnd); + + DWORD dwStyle = WS_BORDER | WS_POPUP; + DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_TOPMOST; + m_pParentWnd = pParentWnd; + return CreateEx( dwExStyle, TITLETIP_CLASSNAME, NULL, dwStyle, 0, 0, 0, 0, + NULL, NULL, NULL ); +} + +/** +* This gets called repeatedly by its parent control. +* Determines whether the text extent of pszTitleText is too big for the +* original rectangle (rectTitle) and displays a TitleTip if required. +* +* @memo Displays the titletip if required. +* +* @param rectTitle rectangle for the original title - in client coordinates +* @param sTitleText text to be displayed +* @param xoffset number of pixel the text is offset from left border of the cell +*/ + +void CTitleTip::Show(CRect rectTitle, CString sTitleText, int xoffset /*=0*/) +{ + ASSERT(::IsWindow(m_hWnd)); + ASSERT(!rectTitle.IsRectEmpty()); + + if(GetFocus() == NULL) // only display titletip if app has focus + return; + + // Define the rectangle outside which the titletip will be hidden. + m_rectTitle.top = 0; + m_rectTitle.left = -xoffset; + m_rectTitle.right = rectTitle.Width() - xoffset; + m_rectTitle.bottom = rectTitle.Height(); + + m_pParentWnd->ClientToScreen(rectTitle); // Determine the width of the text + + CClientDC dc(this); + int iSavedDC = dc.SaveDC(); // Save DC state + + dc.SelectObject(m_pParentWnd->GetFont()); // use same font as ctrl + + CSize size = dc.GetTextExtent(sTitleText); + CRect rectDisplay = rectTitle; + rectDisplay.left += xoffset - GetHorzSpace(); + rectDisplay.right = rectDisplay.left + size.cx + 2 + 2*GetHorzSpace(); + + // Do not display if the text fits within available space + if(size.cx <= rectTitle.Width()-2*xoffset-2) + return; + + // Show the titletip + SetWindowPos(&wndTop, rectDisplay.left, rectDisplay.top, + rectDisplay.Width(), rectDisplay.Height(), + SWP_SHOWWINDOW|SWP_NOACTIVATE); + + + if(m_brshBackground) + { + dc.SetTextColor(m_clrText); + dc.SetBkColor(m_clrBackground); + dc.SetBkMode(OPAQUE); + dc.SelectObject(CBrush::FromHandle(m_brshBackground)); + dc.FillSolidRect(0, 0, rectDisplay.Width(), rectDisplay.Height(), m_clrBackground); + } + else + { + dc.SetBkMode(TRANSPARENT); + } + + dc.TextOut(GetHorzSpace(), 0, sTitleText); + + dc.RestoreDC(iSavedDC); // Restore DC. + + SetCapture(); +} + +/* +* Hide if the mouse is outside the original rectangle. Note that this is +* smaller than the actual window rectangle. +*/ +void CTitleTip::OnMouseMove(UINT nFlags, CPoint point) +{ + if(!m_rectTitle.PtInRect(point)) + { + ReleaseCapture(); + ShowWindow(SW_HIDE); + + // Forward the message + ClientToScreen(&point); + CWnd *pWnd = WindowFromPoint(point); + if(pWnd == this) + pWnd = m_pParentWnd; + int hittest = (int)pWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(point.x,point.y)); + if(hittest == HTCLIENT) + { + pWnd->ScreenToClient(&point); + pWnd->PostMessage(WM_MOUSEMOVE, nFlags, MAKELONG(point.x,point.y)); + } + else + { + pWnd->PostMessage( WM_NCMOUSEMOVE, hittest, MAKELONG(point.x,point.y)); + } + } +} + +BOOL CTitleTip::PreTranslateMessage(MSG* pMsg) +{ + CWnd *pWnd; + int hittest ; + switch(pMsg->message) + { + case WM_LBUTTONDBLCLK: + case WM_RBUTTONDBLCLK: + case WM_MBUTTONDBLCLK: + case WM_LBUTTONUP: + case WM_RBUTTONUP: + case WM_MBUTTONUP: + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + POINTS pts = MAKEPOINTS(pMsg->lParam); + POINT point; + point.x = pts.x; + point.y = pts.y; + ClientToScreen(&point); + pWnd = WindowFromPoint(point); + if(pWnd == this) + pWnd = m_pParentWnd; + + hittest = (int)pWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(point.x,point.y)); + if(hittest == HTCLIENT) + { + pWnd->ScreenToClient(&point); + pMsg->lParam = MAKELONG(point.x,point.y); + } + else + { + switch(pMsg->message) + { + case WM_LBUTTONDOWN: + pMsg->message = WM_NCLBUTTONDOWN; + break; + case WM_RBUTTONDOWN: + pMsg->message = WM_NCRBUTTONDOWN; + break; + case WM_MBUTTONDOWN: + pMsg->message = WM_NCMBUTTONDOWN; + break; + } + pMsg->wParam = hittest; + pMsg->lParam = MAKELONG(point.x,point.y); + ShowWindow(SW_HIDE); + } + pWnd->SendMessage(pMsg->message,pMsg->wParam,pMsg->lParam); + if(GetCapture() == NULL) + SetCapture(); + return TRUE; + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + ReleaseCapture(); + ShowWindow(SW_HIDE); + m_pParentWnd->PostMessage(pMsg->message, pMsg->wParam, pMsg->lParam); + return TRUE; + } + + if(GetFocus() == NULL) + { + ReleaseCapture(); + ShowWindow(SW_HIDE); + return TRUE; + } + + return CWnd::PreTranslateMessage(pMsg); +} diff --git a/D3Launch/TitleTip.h b/D3Launch/TitleTip.h new file mode 100644 index 00000000..2fcc6790 --- /dev/null +++ b/D3Launch/TitleTip.h @@ -0,0 +1,74 @@ +#if !defined(AFX_TITLETIP_H__FB05F243_E98F_11D0_82A3_20933B000000__INCLUDED_) +#define AFX_TITLETIP_H__FB05F243_E98F_11D0_82A3_20933B000000__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// TitleTip.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CTitleTip window + +#define TITLETIP_CLASSNAME _T("ZTitleTip") + +/** +* Titletips similar to tooltips. For ListView controls, TitleTips are used to +* display text of those cells which are not wide enough to display the text +* completely. TitleTips show up as soon as the mouse moves over the cell. +*/ + +class CTitleTip : public CWnd +{ + // Construction +public: + CTitleTip(); + virtual ~CTitleTip(); + + // Attributes +public: + + // Operations +public: + + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CTitleTip) +public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + virtual BOOL Create(CWnd* pParentWnd); + //}}AFX_VIRTUAL + + // Implementation +public: + int GetHorzSpace() {return m_iHorzSpace;} + void SetBackground(HBRUSH brshBackground); + void SetBkColor(COLORREF crColor); + void SetTextColor(COLORREF crColor); + void Show(CRect rectTitle, CString sTitleText, int xoffset = 0); + + static void RegisterWindowClass(); + +protected: + CWnd* m_pParentWnd; + CRect m_rectTitle; + HBRUSH m_brshBackground; + COLORREF m_clrBackground; + COLORREF m_clrText; + int m_iHorzSpace; + + // Generated message map functions +protected: + //{{AFX_MSG(CTitleTip) + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations +// immediately before the previous line. + +#endif // !defined(AFX_TITLETIP_H__FB05F243_E98F_11D0_82A3_20933B000000__INCLUDED_) diff --git a/D3Launch/UpdateDlg.cpp b/D3Launch/UpdateDlg.cpp new file mode 100644 index 00000000..86c66c7c --- /dev/null +++ b/D3Launch/UpdateDlg.cpp @@ -0,0 +1,1401 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/UpdateDlg.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 28 4/15/99 5:02p Nate + * Added localization support for the motd.txt file + * + * 27 3/19/99 10:18a Nate + * Added OEM_GENERIC compile type + * + * 26 2/28/99 5:29p Nate + * Added Auto-Update prompt + * + * 25 2/05/99 3:51p Nate + * Added conditional compilation directives for OEM support + * + * 24 1/28/99 11:28a Nate + * Fixed memory leak + * + * 23 11/03/98 1:04p Nate + * Added label class for user message. + * + * 22 10/21/98 4:51p Nate + * More fixes. + * + * 21 10/20/98 3:18p Nate + * + * 20 10/18/98 2:43p Nate + * Changed version number formatting + * + * 19 10/17/98 5:43p Nate + * Fixed local patch filename in ApplyPatch() + * + * 18 10/13/98 3:03p Nate + * More fixes and changes. + * + * 17 10/12/98 8:17p Nate + * Fixed launcher patching bug + * + * 16 10/12/98 7:13p Nate + * Fixed several bugs. + * + * 15 10/08/98 6:23p Nate + * Fixed a few bugs. + * + * 14 10/05/98 5:33p Nate + * Fixed VC6.0 warnings + * + * 13 10/01/98 3:51p Nate + * Changed some file names and paths. + * + * 12 9/22/98 3:33p Nate + * Added conditional compiling to help system (can toggle between HTML and + * standard windows help) + * + * 11 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 10 9/13/98 2:37p Nate + * Added update file format information. + * + * 9 9/09/98 1:06p Nate + * Added Cleanup() + * + * 8 9/02/98 6:44p Nate + * Added m_should_verify initialization + * + * 7 9/01/98 7:22p Nate + * Fixed GetVersionNFO() bug. + * + * 6 9/01/98 7:15p Nate + * Major Revision #2 + * + * 5 8/31/98 6:44p Nate + * Major Revision + * + * 4 8/25/98 6:15p Nate + * Added the Message of the Day to the Auto Update Dialog + * + * 3 8/24/98 7:07p Nate + * Added new AutoUpdate features, and fixed display glitches + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +// UpdateDlg.cpp : implementation file +// + +// The following are the files used by the Auto-Update system: + +/*************************************************************************************** +version.nfo Format +------------------ + +; Comments <- Note: ';' must be first char on line + +1 00 00 <- first version +http:\\www.outrage.com\update\sites100.nfo <- site file of patches from above version + to latest version + +X XX XX <- next version +http:\\...com <- site file of patches to take this version to the newest version +... +... +... + +N NN NN <- must end with the latest version (that all the other versions will patch to) + +**************************************************************************************** +motd.txt Format +--------------- + +Just make a text file with the text you wish to include in the MOTD box. + +**************************************************************************************** +sites.nfo Format +---------------- + +; Comments <- Note: ';' must be first char on line + +Site #1's Name +Site #1's Location +Site #1's URL +Site #1's patch path (directory and filename) + +... +... +... + +Site #n's Name +Site #n's Location +Site #n's URL +Site #n's patch path (directory and filename) + + +Example: +Outrage's Website +United States +http://www.outrage.com +/updates/patch2.rtp + + +NOTE: +The full path of the patch file to be downloaded will be constructed by +appending the "patch path" to the "URL" + +***************************************************************************************/ + + +#include "stdafx.h" +#include "afxpriv.h" +#include "afxext.h" +#include "D3Launch.h" +#include "D3LaunchDlg.h" +#include "MessageWindowDlg.h" +#include "UpdateDlg.h" +#include "SiteSelectDlg.h" +#include +#include "inetgetfile.h" +#include "OS_Config.h" +#include "io.h" +#include +#include "LaunchNames.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// Globals +//#define WEB_SITE "www.volition-inc.com" +//#define SITE_TYPE "http" + + +bool downloading; // indicates that a download is in progress +bool patching; // indicates that a patch is in progress +bool CancelPressed; // indicates that the user has pressed cancel button +bool UpdateComplete; // indicates that the update has successfully completed + +int update_launcher_status; // indicates if the launcher itself needs updating + +CUpdateDlg *dlg; +uint filesize; +WSADATA wsa_data; + +// Declare the function pointer to get the Patch apply function from the DLL +extern "C" { + unsigned int (pascal *RTPatchApply32)( LPSTR cmdline, LPVOID (CALLBACK *lpfCallback)(UINT id, LPVOID lpParm), BOOL WaitFlag); +} + +///////////////////////////////////////////////////////////////////////////// +// CUpdateDlg dialog + + +CUpdateDlg::CUpdateDlg(CWnd* pParent /*=NULL*/, int should_verify /*=1*/) + : CDialog(CUpdateDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CUpdateDlg) + m_statusbar = _T(""); + m_usermsg = _T(""); + //}}AFX_DATA_INIT + + m_should_verify=should_verify; +} + + +void CUpdateDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CUpdateDlg) + DDX_Control(pDX, IDC_USERMSG, m_UserMsgStatic); + DDX_Control(pDX, IDC_LATEST_VERSION_EDIT, m_LatestVersionEdit); + DDX_Control(pDX, IDC_YOUR_VERSION_EDIT, m_YourVersionEdit); + DDX_Control(pDX, IDC_MOTD_EDIT, m_MOTDBox); + DDX_Control(pDX, IDC_PROGRESS1, m_progress); + DDX_Control(pDX, IDC_LIST1, m_list); + DDX_Text(pDX, IDC_STATUSBAR, m_statusbar); + DDX_Text(pDX, IDC_USERMSG, m_usermsg); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CUpdateDlg, CDialog) + //{{AFX_MSG_MAP(CUpdateDlg) + ON_BN_CLICKED(IDYES, OnYes) + ON_WM_CLOSE() + ON_MESSAGE(WM_COMMANDHELP,OnCommandHelp) + ON_WM_HELPINFO() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CUpdateDlg message handlers + + +// Downloads the version info, and checks to see if the user needs to update +BOOL CUpdateDlg::GetVersionNfo() +{ + int get_file_ret; + + // Download the version info file + if (!(InitHTTP())) { + LocalizedMessageBox(IDS_UPDATEDLG_NO_CON,IDS_UPDATEDLG_ERROR,MB_OK|MB_ICONERROR); + return FALSE; + } + AddToList(IDS_UPDATEDLG_GVN_MSG2); + + get_file_ret=GetHTTPFile(VERSION_PATH, VERSION_LOC_FNAME); + if (get_file_ret != GETHTTPFILE_OK) { + CloseHTTP(); + GetHTTPFileErrorBox(get_file_ret,VERSION_PATH, VERSION_LOC_FNAME); + return FALSE; + } + CloseHTTP(); + + // parse the most up to date version number out of the file + FILE *f = fopen(VERSION_LOC_FNAME, "rt"); + if (f==NULL) { + LocalizedMessageBox(IDS_UPDATEDLG_NO_FIND,IDS_UPDATEDLG_ERROR,MB_OK|MB_ICONERROR); + return FALSE; + } + + // grab the last line in file which isn't empty and isn't a comment + char buffer[PSPATHNAME_LEN+1], verbuffer[PSPATHNAME_LEN+1]; + + strcpy(verbuffer,""); + strcpy(buffer,""); + while (!feof(f)) { + + // Read the line into a temporary buffer + fgets(buffer, PSPATHNAME_LEN, f); + + // take the \n off the end of it + if(strlen(buffer)>0 && buffer[strlen(buffer) - 1] == '\n') + buffer[strlen(buffer) - 1] = 0; + + // If the line is empty, go get another one + if(strlen(buffer)==0) continue; + + // If the line is a comment, go get another one + if(buffer[0]==VERSION_FILE_COMMENT_CHAR) continue; + + // Line is a good one, so save it... + strcpy(verbuffer,buffer); + } + fclose(f); + + // Make sure a version line was found + if(strlen(verbuffer)==0) { + LocalizedMessageBox(IDS_UPDATEDLG_NO_FIND,IDS_UPDATEDLG_ERROR,MB_OK|MB_ICONERROR); + return FALSE; + } + + // Get the most up to date Version number + NewMajor=0; NewMinor=0; NewBuild=0; + if(sscanf(verbuffer, "%i %i %i", &NewMajor, &NewMinor, &NewBuild) != 3) { + LocalizedMessageBox(IDS_UPDATEDLG_NO_FIND,IDS_UPDATEDLG_ERROR,MB_OK|MB_ICONERROR); + return FALSE; + } + + // retrieve the user's current version + UsrMajor = os_config_read_uint("Version", "Major", 0); + UsrMinor = os_config_read_uint("Version", "Minor", 0); + UsrBuild = os_config_read_uint("Version", "Build", 0); + + // Make sure the user's Version was found! + if (VER(UsrMajor, UsrMinor, UsrBuild)==0) { + LocalizedMessageBox(IDS_UPDATEDLG_NOREGVER_MSG,IDS_UPDATEDLG_NOREGVER_TITLE,MB_OK|MB_ICONERROR); + return FALSE; + } + + // Display the versions in their respective boxes + DisplayVersions(UsrMajor,UsrMinor,UsrBuild,NewMajor,NewMinor,NewBuild); + + // check to see if the user's version is up to date + if (VER(UsrMajor, UsrMinor, UsrBuild) < VER(NewMajor, NewMinor, NewBuild)) { + + // Change the user message to a bold dark red + m_UserMsgStatic.SetTextColor(PALETTERGB(128,0,0)); + //m_UserMsgStatic.SetFontBold(TRUE); + + // Light up the progress bar + // (as further indicator that user's version is already complete) + m_progress.SetRange(0,100); + m_progress.SetPos(0); + + // Display the user message + AddToList(IDS_UPDATEDLG_SRV); + StatusBar(IDS_UPDATEDLG_WAIT); + m_usermsg.LoadString(IDS_UPDATEDLG_USERMSG1); + UpdateData(FALSE); + return TRUE; + } + + // Version is ok, so dim the cancel button, and un-dim the ok/yes button + HWND hwnd; + GetDlgItem(IDYES,&hwnd); + ::EnableWindow(hwnd,TRUE); + GetDlgItem(IDCANCEL,&hwnd); + ::EnableWindow(hwnd,FALSE); + GetDlgItem(IDYES,&hwnd); + ::SetFocus(hwnd); + + // Light up the progress bar + // (as further indicator that user's version is already complete) + m_progress.SetRange(0,100); + m_progress.SetPos(100); + + // The user does not need to do any patching + UpdateComplete = TRUE; + + // Inform the user that his version is up to date + AddToList(IDS_UPDATEDLG_SRV); + AddToList(IDS_UPDATEDLG_UTDT); + StatusBar(IDS_UPDATEDLG_WAIT); + m_usermsg.Format( IDS_UPDATEDLG_UTD, UsrMajor, UsrMinor, UsrBuild ); + UpdateData(FALSE); + + return TRUE; +} + +// Downloads the Message of the Day +BOOL CUpdateDlg::GetMOTD() +{ + int get_file_ret; + + AddToList(IDS_UPDATEDLG_GVN_MSG1); + if (!(InitHTTP())) { + LocalizedMessageBox(IDS_UPDATEDLG_NO_CON,IDS_UPDATEDLG_ERROR,MB_OK|MB_ICONERROR); + EndDialog(0); + return FALSE; + } + +#ifdef USE_MULTI_LANGUAGES + int lang_type=os_config_read_uint(szSectionName,"LanguageType",LANGUAGE_ENGLISH); + if(lang_type!=LANGUAGE_ENGLISH) { + char *path=NULL; + switch(lang_type) { + case LANGUAGE_FRENCH: + path=FRN_MOTD_PATH; + break; + case LANGUAGE_GERMAN: + path=GER_MOTD_PATH; + break; + case LANGUAGE_ITALIAN: + path=ITN_MOTD_PATH; + break; + case LANGUAGE_SPANISH: + path=SPN_MOTD_PATH; + break; + } + + // See if a motd file exists for this language + if(path!=NULL) { + get_file_ret=GetHTTPFile(path, MOTD_LOC_FNAME); + if (get_file_ret == GETHTTPFILE_OK) { + CloseHTTP(); + return TRUE; + } + } + } +#endif + + get_file_ret=GetHTTPFile(MOTD_PATH, MOTD_LOC_FNAME); + if (get_file_ret != GETHTTPFILE_OK) { + CloseHTTP(); + GetHTTPFileErrorBox(get_file_ret,MOTD_PATH, MOTD_LOC_FNAME); + + // If can't get MOTD, just display the error box and set + // the MOTD to "no message" (don't close down the dialog) + CString MOTD_buffer; + MOTD_buffer.LoadString(IDS_UPDATEDLG_NO_MOTD); + m_MOTDBox.ReplaceSel(MOTD_buffer.GetBuffer(0)); + return FALSE; + } + CloseHTTP(); + + return TRUE; +} + +// Start the update (download and patch) process +void CUpdateDlg::OnYes() +{ + // if the update has already been completed, then pressing the + // yes/OK button merely closes down the Update dialog + // (or the entire launcher if a launcher update needs to be performed) + if(UpdateComplete) { + + // Display launcher update messages + switch(update_launcher_status) { + case LAUNCHER_REPLACE_NONE: + break; + case LAUNCHER_REPLACE_ACCESS_ERROR: + LocalizedMessageBox(IDS_UPDATEDLG_LNCH_UPD3, IDS_UPDATEDLG_LNCH_UPD_TITLE, MB_OK|MB_ICONERROR); + break; + case LAUNCHER_REPLACE_CREATEPROC_ERROR: + LocalizedMessageBox(IDS_UPDATEDLG_LNCH_UPD2, IDS_UPDATEDLG_LNCH_UPD_TITLE, MB_OK|MB_ICONERROR); + break; + case LAUNCHER_REPLACE_NEEDED: + LocalizedMessageBox(IDS_UPDATEDLG_LNCH_UPD1, IDS_UPDATEDLG_LNCH_UPD_TITLE, MB_OK|MB_ICONINFORMATION); + break; + } + + // Remove the temporary files + Cleanup(); + + // If the launcher needs to be updated, shut down the entire launcher + if(update_launcher_status==LAUNCHER_REPLACE_NEEDED) { + EndDialog(IDSHUTDOWN); + return; + } + + // Otherwise, just close down the Update dialog + EndDialog(0); + return; + } + + // TODO: Add your control notification handler code here + char buffer[PSPATHNAME_LEN+1]; + char verbuffer[PSPATHNAME_LEN+1], filebuffer[PSPATHNAME_LEN+1]; + uint major, minor, build; + int get_file_ret; + CString str_msg; + int line_num; + char *filename_only; + + FILE *f; + + // Default to not updating the launcher + update_launcher_status=LAUNCHER_REPLACE_NONE; + + // Dim the YES/OK button and focus on the cancel button + HWND hwnd; + GetDlgItem(IDYES,&hwnd); + ::EnableWindow(hwnd,FALSE); + GetDlgItem(IDCANCEL,&hwnd); + ::SetFocus(hwnd); + + // Change the user message back to normal + m_UserMsgStatic.SetTextColor(PALETTERGB(0,0,0)); + //m_UserMsgStatic.SetFontBold(FALSE); + + // Set progress bar range to that of a percentage (0-100) + m_progress.SetRange(0,100); + + // Open the version file + f = fopen(VERSION_LOC_FNAME, "rt"); + if(f == NULL){ + LocalizedMessageBox(IDS_UPDATEDLG_YES_ERR1,IDS_UPDATEDLG_ERROR,MB_OK|MB_ICONERROR); + EndDialog(0); + return; + } + + // Read in groups of lines: + // line 0 - the Version number + // line 1 - full path to the sites.NFO file for the patch + line_num=0; + strcpy(buffer,""); + while (!feof(f)) { + + // Read the line into a temporary buffer + fgets(buffer, PSPATHNAME_LEN, f); + + // take the \n off the end of it + if(strlen(buffer)>0 && buffer[strlen(buffer) - 1] == '\n') + buffer[strlen(buffer) - 1] = 0; + + // If the line is empty, go get another one + if(strlen(buffer)==0) continue; + + // If the line is a comment, go get another one + if(buffer[0]==VERSION_FILE_COMMENT_CHAR) continue; + + // Read in the appropriate line + switch(line_num) { + case 0: + strcpy(verbuffer, buffer); + sscanf(verbuffer, "%i %i %i", &major, &minor, &build); + break; + case 1: + strcpy(filebuffer, buffer); + break; + } + line_num++; + + // If a set of lines hasn't been read in yet, get the rest + if(line_num < 2) continue; + + // Reset the current line for the next set + line_num=0; + + + // If read in version is larger than user's version, update it! + if (VER(major, minor, build) == VER(UsrMajor, UsrMinor, UsrBuild)) { + + // Download the site info file + filename_only=strrchr(filebuffer,'/'); + if(filename_only==NULL) + filename_only=filebuffer; + else + filename_only++; + str_msg.Format(IDS_UPDATEDLG_GET_FILE,filename_only); + DebugSpew(str_msg); + + if (!(InitHTTP())) { + LocalizedMessageBox(IDS_UPDATEDLG_NO_CON,IDS_UPDATEDLG_ERROR,MB_OK|MB_ICONERROR); + EndDialog(0); + return; + } + + get_file_ret=GetHTTPFile(filebuffer, SITES_LOC_FNAME); + if (get_file_ret!=GETHTTPFILE_OK) { + CloseHTTP(); + fclose(f); + Cleanup(); + + // Output the appropriate error message + GetHTTPFileErrorBox(get_file_ret, filebuffer, SITES_LOC_FNAME); + + EndDialog(0); + return; + } + CloseHTTP(); + + // Display the site selection dialog + CSiteSelectDlg site_select_dlg; + + int nResponse = site_select_dlg.DoModal(); + if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + fclose(f); + return; + } + + // If no site was selected, return + if(strlen(site_select_dlg.download_path)==0) { + fclose(f); + return; + } + + + // Download the patch file + filename_only=strrchr(site_select_dlg.download_path,'/'); + if(filename_only==NULL) + filename_only=site_select_dlg.download_path; + else + filename_only++; + str_msg.Format(IDS_UPDATEDLG_GET_FILE,filename_only); + DebugSpew(str_msg); + + if (!(InitHTTP())) { + LocalizedMessageBox(IDS_UPDATEDLG_NO_CON,IDS_UPDATEDLG_ERROR,MB_OK|MB_ICONERROR); + EndDialog(0); + return; + } + + get_file_ret=GetHTTPFile(site_select_dlg.download_path, PATCH_LOC_FNAME); + if (get_file_ret!=GETHTTPFILE_OK) { + CloseHTTP(); + fclose(f); + Cleanup(); + + // Output the appropriate error message + GetHTTPFileErrorBox(get_file_ret,site_select_dlg.download_path,PATCH_LOC_FNAME); + + EndDialog(0); + return; + } + CloseHTTP(); + + str_msg.Format(IDS_UPDATEDLG_PATCHING, NewMajor, NewMinor, NewBuild); + DebugSpew(str_msg); + + m_usermsg.Format(IDS_UPDATEDLG_USERMSG3,NewMajor,NewMinor,NewBuild); + UpdateData(FALSE); + + if (!ApplyPatch()) { + fclose(f); + Cleanup(); + LocalizedMessageBox(IDS_UPDATEDLG_CANT_PATCH, IDS_UPDATEDLG_ERROR, MB_OK|MB_ICONERROR); + EndDialog(0); + return; + } + + // Set list view so that all the patch results fit in window + //int i = m_list.GetCount(); + //i -= 17; + //i = max(0,i); + //m_list.SetTopIndex(i); + UpdateData(FALSE); + + // check if the launcher needs to be updated + update_launcher_status=UpdateTheLauncher(); + + // Write out the updated version number to registry and break out of loop + UsrMajor = NewMajor; + UsrMinor = NewMinor; + UsrBuild = NewBuild; + os_config_write_uint("Version", "Major", UsrMajor); + os_config_write_uint("Version", "Minor", UsrMinor); + os_config_write_uint("Version", "Build", UsrBuild); + + // Display the user's new version in its edit box + DisplayVersions(UsrMajor,UsrMinor,UsrBuild); + + break; + + } else { + CString str_msg; + filename_only=strrchr(filebuffer,'/'); + if(filename_only==NULL) + filename_only=filebuffer; + else + filename_only++; + str_msg.Format(IDS_UPDATEDLG_SKIPPING,filename_only); + DebugSpew(str_msg); + } + + DeferMessages(); + } + + fclose(f); + Cleanup(); + LocalizedMessageBox(IDS_UPDATEDLG_PATCH_OK, IDS_UPDATEDLG_SUCCESS, MB_OK|MB_ICONINFORMATION); + + // Dim the cancel button, and un-dim the ok/yes button + GetDlgItem(IDYES,&hwnd); + ::EnableWindow(hwnd,TRUE); + GetDlgItem(IDCANCEL,&hwnd); + ::EnableWindow(hwnd,FALSE); + GetDlgItem(IDYES,&hwnd); + ::SetFocus(hwnd); + + // The patching process has completed successfully!!! + UpdateComplete = TRUE; + + // Update status info + StatusBar(IDS_UPDATEDLG_DONE_UPDATING); + m_usermsg.LoadString(IDS_UPDATEDLG_CONTINUE_MSG); + UpdateData(FALSE); + DeferMessages(); + + return; +} + +void CUpdateDlg::OnCancel() +{ + // TODO: Add extra cleanup here + CancelPressed = TRUE; + + // Only close it down if we're not downloading! + if(!downloading && !patching) { + Cleanup(); + EndDialog(0); + return; + //CDialog::OnCancel(); + } +} + +// Setup the dialog by displaying a temporary connection message, and then +// grabbing the Version info and Message of the Day files +BOOL CUpdateDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + m_progress.SetRange(0,100); + m_progress.SetPos(0); + UpdateComplete = FALSE; + CancelPressed = FALSE; + downloading = FALSE; + patching = FALSE; + dlg=NULL; + + // Don't put a limit on the MOTD box + m_MOTDBox.LimitText(0); + m_MOTDBox.SetMargins(5,5); + + // Display the temporary message window + msg_dlg.m_WndMsgMain.LoadString(IDS_UPDATEDLG_WNDMSG_MAIN); + msg_dlg.m_WndMsgStatus.LoadString(IDS_UPDATEDLG_WNDMSG_STATUS); + msg_dlg.Create(IDD_MESSAGE_WINDOW,this); + msg_dlg.ShowWindow(SW_SHOW); + + // Display wait cursor in case verification takes a while + CWaitCursor wc; + + // Download the Message of the Day text file + if(GetMOTD() && ParseMOTDFile()) + AddToList(IDS_UPDATEDLG_DL_MOTD); + else + AddToList(IDS_UPDATEDLG_NODL_MOTD); + + // Get the Version info file and check it (if user didn't press Cancel already) + if (CancelPressed || !GetVersionNfo()){ + Cleanup(); + msg_dlg.EndDialog(0); + EndDialog(0); + return FALSE; + } + + // Set the font for the data list to a fixed-width font + // (so the patching output looks good) + if( m_listfont.CreateFont( 15, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, _T("Courier New") )) + m_list.SetFont(&m_listfont); + + // Get rid of the temporary message window + msg_dlg.EndDialog(0); + + // Don't need to show update prompt if user's been here already + os_config_write_uint(NULL,"UpdatePromptShown",1); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +// Cleans a string of any new lines or carriage returns +char *CleanString(char *src) +{ + CString temp; + unsigned int j; + + // Allocate a temporary string workspace + temp=""; + + // Only copy over wantedcharacters + for(j=0; j < strlen(src); j++) { + if(src[j]!='\n' && src[j]!='\r') { + temp+=src[j]; + } + } + strcpy(src,temp.GetBuffer(0)); + return src; +} + + +// Callback function for patch application (reports status messages from patch process) +__declspec( dllexport ) +LPVOID CALLBACK CallBack( UINT Id, LPVOID Parm ) +{ + CString temp_msg; + LPVOID RetVal; + + RetVal = ""; + + // do a few messages while we're here.. + DeferMessages(); + + if (dlg) { + + switch( Id ) + { + case 1: + // Warning message header + case 2: + // Warning message text + dlg->DebugSpew(CleanString((char *)Parm)); + break; + case 3: + // Error message header + break; + case 4: + // Error message text + temp_msg.LoadString(IDS_UPDATEDLG_PATCH_ERROR); + MessageBox(NULL, CleanString((char *)Parm), temp_msg, MB_OK|MB_ICONERROR); + break; + case 5: + // % completed + dlg->m_progress.SetPos(*(UINT *)Parm); + break; + case 6: + // Number of patch files + // PATCHGUI ignores this + break; + case 7: + // begin patch + temp_msg.Format(IDS_UPDATEDLG_PROCESSING,(char *)Parm); + dlg->StatusBar( temp_msg.GetBuffer(0) ); // put on status line + // max out the progress meter + dlg->m_progress.SetPos(0x0000); + break; + case 8: + // end patch + dlg->StatusBar(IDS_UPDATEDLG_FILE_COMPLETE); + // max out the progress meter + dlg->m_progress.SetPos(0x8000); + break; + case 9: + // progress message + dlg->DebugSpew(CleanString((char *)Parm)); + break; + case 0xa: + // help message + //dlg->DebugSpew(CleanString((char *)Parm)); + break; + case 0xb: + // patch file comment + //dlg->DebugSpew(CleanString((char *)Parm)); + break; + case 0xc: + // copyright message + //WriteIt( (char *) Parm ); + break; + case 0xd: + // this one shouldn't happen (only occurs if the command line + // doesn't have a patch file in it, and we insure that it does). + break; + case 0xe: + // this one shouldn't happen either (same reason) + break; + case 0xf: + // Password Dialog + // lpProcDlg = MakeProcInstance( PasswordProc, hInst ); + // DialogBox( hInst, "PasswordDialog", hwnd, lpProcDlg); + // FreeProcInstance( lpProcDlg ); + //InCallBack = FALSE; + // RetVal = Password; + break; + case 0x10: + // Invalid Password Alert + // if (IDCANCEL == + // MessageBox( + // hwnd, + // "Password entered was incorrect. A valid \npassword is required to apply this patch.", + // "Invalid Password", + // MB_OKCANCEL | MB_ICONEXCLAMATION )) + // AbortPatch = TRUE; + break; + case 0x11: + // Disk Change Dialog + // lpProcDlg = MakeProcInstance( DiskChgProc, hInst ); + // DialogBox( hInst, "DiskChangeDialog", hwnd, lpProcDlg); + // FreeProcInstance( lpProcDlg ); + break; + case 0x12: + // Disk Change Alert + // if (IDCANCEL == + // MessageBox( + // hwnd, + // "Invalid patch disk was inserted.\nPlease insert the correct disk.", + // "Invalid patch disk", + // MB_OKCANCEL | MB_ICONEXCLAMATION )) + // AbortPatch = TRUE; + break; + case 0x13: + // Confirmation Dialog + // lpProcDlg = MakeProcInstance( ConfirmProc, hInst ); + // DialogBox( hInst, "ConfirmationDialog", hwnd, lpProcDlg); + // FreeProcInstance( lpProcDlg ); + // InCallBack = FALSE; + // RetVal = YNString; + break; + case 0x14: + // Location Dialog + // lpProcDlg = MakeProcInstance( LocationProc, hInst ); + // DialogBox( hInst, "LocationDialog", hwnd, lpProcDlg); + // FreeProcInstance( lpProcDlg ); + // InCallBack = FALSE; + // RetVal = SystemLocation; + break; + case 0x16: + // Searching Call-back + // PutStatus( "Searching for Systems to Update..." ); + temp_msg.LoadString(IDS_UPDATEDLG_SEARCHING); + dlg->DebugSpew(temp_msg); + break; + case 0x15: + // Idle... + default: + break; + } + } + + // do a few more messages while we're here... + DeferMessages(); + + if (CancelPressed) // all of our call-back dialogs set this + // flag if the user pushes a CANCEL button + return (NULL); + else + return (RetVal); +} + + +// This function attempts to open the .RTPatch dll and apply the downloaded +// patch to the game, returning TRUE if successful +BOOL CUpdateDlg::ApplyPatch() +{ + char patch_cmd_line[1024]; + + HMODULE patchlib = LoadLibrary(PATCH_DLL_FNAME); + if (!patchlib) { + LocalizedMessageBox(IDS_UPDATEDLG_NO_PATCH_LIB, IDS_UPDATEDLG_ERROR, MB_OK|MB_ICONERROR); + return FALSE; + } + + patching=TRUE; + sprintf(patch_cmd_line,"-undo %s",PATCH_LOC_FNAME); + RTPatchApply32 = (unsigned int (__stdcall *)(char *,void *(__stdcall *)(unsigned int,void *),int))GetProcAddress(patchlib, "RTPatchApply32@12"); + if (RTPatchApply32) { + m_progress.SetRange(0,short(0x8000)); + m_progress.SetPos(0); + dlg = this; + StatusBar(IDS_UPDATEDLG_BEG_PATCH); + if (!(RTPatchApply32(patch_cmd_line, CallBack, TRUE))) { + FreeLibrary(patchlib); + StatusBar(IDS_UPDATEDLG_PATCH_COMPLETE); + patching=FALSE; + return TRUE; + } else { + FreeLibrary(patchlib); + StatusBar(IDS_UPDATEDLG_PATCH_FAILED); + patching=FALSE; + return FALSE; + } + } + + FreeLibrary(patchlib); + patching=FALSE; + return FALSE; +} + + +// Checks to see if the Launcher needs to be updated, +// and, if it does, starts up the LauncherUpdate program +// and shuts down the launcher +int CUpdateDlg::UpdateTheLauncher() +{ + // if the new launcher replacement file doesn't exist, + // and the launcher patch file doesn't exist, + // then we don't need to replace the launcher + + if( _access(NEW_LAUNCHER_FNAME,0x00) != -1) { // does new executable exist? + + // make sure the replacement file has read/write access + if( _access(NEW_LAUNCHER_FNAME,0x06) == -1) { + // File doesn't have read/write access, so give it access + if( _chmod(NEW_LAUNCHER_FNAME, _S_IREAD | _S_IWRITE ) == -1) + return LAUNCHER_REPLACE_ACCESS_ERROR; + } + + } + else if( _access(LAUNCHER_PATCH_FNAME,0x00) != -1) { // does patch file exist? + + // make sure the replacement file has read/write access + if( _access(LAUNCHER_PATCH_FNAME,0x06) == -1) { + // File doesn't have read/write access, so give it access + if( _chmod(LAUNCHER_PATCH_FNAME, _S_IREAD | _S_IWRITE ) == -1) + return LAUNCHER_REPLACE_ACCESS_ERROR; + } + + } + else + return LAUNCHER_REPLACE_NONE; // neither exists, so don't do anything + + // verify that the UpdateLauncher executable exists + if( _access(REPLACER_FNAME,0x00) == -1) + return LAUNCHER_REPLACE_CREATEPROC_ERROR; + + // fire up the UpdateLauncher executable + STARTUPINFO si; + PROCESS_INFORMATION pi; + CString CommandLine; + + CommandLine.Format("%s %s",REPLACER_FNAME,szTitle.GetBuffer(0)); + + memset( &si, 0, sizeof(STARTUPINFO) ); + si.cb = sizeof(si); + + BOOL ret = CreateProcess( REPLACER_FNAME, // pointer to name of executable module + CommandLine.GetBuffer(0), // pointer to command line string + NULL, // pointer to process security attributes + NULL, // pointer to thread security attributes + FALSE, // handle inheritance flag + CREATE_DEFAULT_ERROR_MODE, // creation flags + NULL, // pointer to new environment block + NULL, // pointer to current directory name + &si, // pointer to STARTUPINFO + &pi // pointer to PROCESS_INFORMATION + ); + + if (!ret) return LAUNCHER_REPLACE_CREATEPROC_ERROR; + + // return "close down the Launcher" ID + return LAUNCHER_REPLACE_NEEDED; + +} + +// Downloads a given remote file and saves it as a local file +int CUpdateDlg::GetHTTPFile(char *remote, char *local) +{ + unsigned int LastPrintbytes = time(NULL); + InetGetFile *inetfile; + WORD ver=MAKEWORD(1,1); + char URL[PSPATHNAME_LEN+1]; + + //sprintf(URL,"%s://%s%s",SITE_TYPE,WEB_SITE,remote); + strcpy(URL,remote); + m_progress.SetRange(0,100); + m_progress.SetPos(0); + + CancelPressed=FALSE; + downloading=TRUE; + inetfile = new InetGetFile(URL,local); + do + { + // Check if a download error has occurred + if(inetfile->IsFileError()) + { + int new_error; + int error=inetfile->GetErrorCode(); + delete inetfile; + downloading=FALSE; + + switch(error) { + case INET_ERROR_BADPARMS: + new_error=GETHTTPFILE_BADPARMS; + break; + case INET_ERROR_CANT_WRITE_FILE: + new_error=GETHTTPFILE_CANT_WRITE_FILE; + break; + case INET_ERROR_CANT_PARSE_URL: + new_error=GETHTTPFILE_CANT_PARSE_URL; + break; + case INET_ERROR_BAD_FILE_OR_DIR: + new_error=GETHTTPFILE_BAD_FILE_OR_DIR; + break; + case INET_ERROR_HOST_NOT_FOUND: + new_error=GETHTTPFILE_HOST_NOT_FOUND; + break; + case INET_ERROR_NO_MEMORY: + new_error=GETHTTPFILE_NO_MEMORY; + break; + case INET_ERROR_UNKNOWN_ERROR: + default: + new_error=GETHTTPFILE_UNKNOWN_ERROR; + break; + } + + return new_error; + } + + // check if the file has been received + if(inetfile->IsFileReceived()) + { + delete inetfile; + downloading=FALSE; + //m_progress.SetPos(100); + return GETHTTPFILE_OK; + } + + // update the download status information + if(time(NULL)-LastPrintbytes>=1) + { + if(inetfile->GetTotalBytes()) + { + int ipct=0; + + if(inetfile->GetTotalBytes()!=0) + ipct = int(100.0*(double(inetfile->GetBytesIn())/double(inetfile->GetTotalBytes()))); + + m_usermsg.Format(IDS_UPDATEDLG_USERMSG2,inetfile->GetBytesIn(),inetfile->GetTotalBytes(),ipct); + UpdateData(FALSE); + + m_progress.SetPos(ipct); + StatusBar(IDS_UPDATEDLG_DL_FILE); + } + LastPrintbytes = time(NULL); + } + + // See if cancel has been pushed + DeferMessages(); + + }while(!CancelPressed); //}while(!CancelPressed || !inetfile->IsReceiving()); + + inetfile->AbortGet(); + delete inetfile; + downloading=FALSE; + + return GETHTTPFILE_CANCELLED; +} + +// Displays the appropriate error message box for a GetHTTPFile() error +void CUpdateDlg::GetHTTPFileErrorBox(int error_id, char *remote, char *local) +{ + CString msg, title; + + // Make sure the data is not NULL + if(remote==NULL || local==NULL) return; + + // Make sure an error has occurred + if(error_id==GETHTTPFILE_OK) return; + + // Set the message body according to the given error + switch(error_id) { + case GETHTTPFILE_BADPARMS: + msg.Format(IDS_UPDATEDLG_BADPARMS,remote,local); + break; + case GETHTTPFILE_CANT_WRITE_FILE: + msg.Format(IDS_UPDATEDLG_CANT_WRITE_FILE,local); + break; + case GETHTTPFILE_CANT_PARSE_URL: + msg.Format(IDS_UPDATEDLG_CANT_PARSE_URL,remote); + break; + case GETHTTPFILE_BAD_FILE_OR_DIR: + msg.Format(IDS_UPDATEDLG_BAD_FILE_OR_DIR,remote,local); + break; + case GETHTTPFILE_HOST_NOT_FOUND: + msg.Format(IDS_UPDATEDLG_HOST_NOT_FOUND,remote); + break; + case GETHTTPFILE_NO_MEMORY: + msg.Format(IDS_UPDATEDLG_NO_MEMORY); + break; + case GETHTTPFILE_CANCELLED: + msg.Format(IDS_UPDATEDLG_CANCELLED); + break; + case GETHTTPFILE_UNKNOWN_ERROR: + default: + msg.Format(IDS_UPDATEDLG_UNKNOWN_ERROR); + break; + } + + title.LoadString(IDS_UPDATEDLG_DOWNLOAD_ERROR); + + MessageBox(msg,title, MB_OK | MB_ICONWARNING); +} + + +// Send a string to the output message list +void CUpdateDlg::DebugSpew(CString &msg) +{ + DebugSpew(msg.GetBuffer(0)); +} + +void CUpdateDlg::DebugSpew(char *data) +{ + m_list.AddString(data); + + int i = m_list.GetCount(); + i -= 13; + i = max(0,i); + + m_list.SetTopIndex(i); + + UpdateData(FALSE); +} + +BOOL CUpdateDlg::InitHTTP() +{ + WORD ver=MAKEWORD(1,1); + + StatusBar(IDS_UPDATEDLG_INIT_CON); + m_usermsg.Format(""); + UpdateData(FALSE); + DeferMessages(); + + if (WSAStartup(ver, &wsa_data )) { + StatusBar(IDS_UPDATEDLG_WS_ERR); + return FALSE; + } + + // Succeeded + StatusBar(IDS_UPDATEDLG_CON_OK); + DeferMessages(); + return TRUE; +} + +void CUpdateDlg::CloseHTTP() +{ + StatusBar(IDS_UPDATEDLG_CON_SHUTDOWN); + m_usermsg.Format(""); + UpdateData(FALSE); + DeferMessages(); + + if (WSACleanup()) { + //mprintf(( "Error closing wsock!" )); + } + + StatusBar(IDS_UPDATEDLG_WAITING); + DeferMessages(); +} + +void CUpdateDlg::StatusBar(UINT strID) +{ + m_statusbar.LoadString(strID); + UpdateData(FALSE); +} + +void CUpdateDlg::StatusBar(char *status) +{ + m_statusbar=status; + UpdateData(FALSE); +} + +void CUpdateDlg::LocalizedMessageBox(UINT msgID, UINT titleID, UINT type /*=MB_OK*/) +{ + CString msg, title; + + msg.LoadString(msgID); + title.LoadString(titleID); + MessageBox(msg,title,type); +} + +void CUpdateDlg::AddToList(UINT strID) +{ + CString msg; + + msg.LoadString(strID); + m_list.AddString(msg); +} + +void CUpdateDlg::OnClose() +{ + // TODO: Add your message handler code here and/or call default + CancelPressed = TRUE; // in case downloading, cancel out first + + // If the update process is complete, call the OnYes() callback in case + // the launcher needs to be updated + if(UpdateComplete) OnYes(); + + // Only close it down if we're not downloading! + if(!downloading && !patching) { + Cleanup(); + EndDialog(0); + return; + //CDialog::OnClose(); + } +} + +// Reads the message of the day text from the file +// into the edit box +BOOL CUpdateDlg::ParseMOTDFile(void) +{ + CString MOTD_buffer; + char filebuffer[4096+1]; + FILE *f; + BOOL add_new_line; + + // Try and open the message of the day local text file + f = fopen(MOTD_LOC_FNAME, "rt"); + if(f == NULL){ + // Couldn't open file, so insert default message + MOTD_buffer.LoadString(IDS_UPDATEDLG_NO_MOTD); + m_MOTDBox.SetWindowText(MOTD_buffer.GetBuffer(0)); + return FALSE; + } + + // Read in the Message of the Day text + MOTD_buffer=""; + while (!feof(f)) { + + strcpy(filebuffer,""); + fgets(filebuffer, 4096, f); + + // Check if new line is on the end + add_new_line=FALSE; + if(strlen(filebuffer)>0 && filebuffer[strlen(filebuffer) - 1] == '\n') { + filebuffer[strlen(filebuffer) - 1] = '\0'; + add_new_line=TRUE; + } + + MOTD_buffer += filebuffer; + + // If need to add new line, add both carriage return and line feed + MOTD_buffer += "\r\n"; + } + fclose(f); + + m_MOTDBox.SetWindowText(MOTD_buffer.GetBuffer(0)); + + return TRUE; +} + +// Displays the user's version, +// and (if desired) the latest version in the Version boxes +void CUpdateDlg::DisplayVersions(int maj1, int min1, int bld1, + int maj2 /*=-1*/, int min2 /*=-1*/, int bld2 /*=-1*/) +{ + CString ver_buffer; + + // display user's version + ver_buffer.Format("%d.%d.%d",maj1,min1,bld1); + m_YourVersionEdit.SetWindowText(ver_buffer.GetBuffer(0)); + + // If not entered, don't display the latest version + if(maj2==-1 && min2==-1 && bld2==-1) return; + + // display latest version + ver_buffer.Format("%d.%d.%d",maj2,min2,bld2); + m_LatestVersionEdit.SetWindowText(ver_buffer.GetBuffer(0)); +} + + +#define MAX_NUM_DELETE_TRIES 1 // number of times to try and delete file +#define DELETE_WAIT_TIME 0 // wait this long (in msecs) if delete try failed + +// Performs cleanup (deletes temporary files) +void CUpdateDlg::Cleanup(void) +{ + int num_tries; + + // Delete the version file + num_tries=0; + while(!DeleteFile(VERSION_LOC_FNAME) && num_tries= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// UpdateDlg.h : header file +// + +#include "PsTypes.h" +#include "MessageWindowDlg.h" +#include "Label.h" + +///////////////////////////////////////////////////////////////////////////// +// CUpdateDlg dialog + +// Return values for UpdateTheLauncher() +#define LAUNCHER_REPLACE_NONE 0 +#define LAUNCHER_REPLACE_ERROR 1 +#define LAUNCHER_REPLACE_NEEDED 2 +#define LAUNCHER_REPLACE_ACCESS_ERROR 3 +#define LAUNCHER_REPLACE_CREATEPROC_ERROR 4 + +// Return values for GetHTTPFile +#define GETHTTPFILE_OK 0 +#define GETHTTPFILE_UNKNOWN_ERROR 1 +#define GETHTTPFILE_CANCELLED 2 +#define GETHTTPFILE_BADPARMS 3 +#define GETHTTPFILE_CANT_WRITE_FILE 4 +#define GETHTTPFILE_CANT_PARSE_URL 5 +#define GETHTTPFILE_BAD_FILE_OR_DIR 6 +#define GETHTTPFILE_HOST_NOT_FOUND 7 +#define GETHTTPFILE_NO_MEMORY 8 + +class CUpdateDlg : public CDialog +{ +// Construction +public: + int m_should_verify; // should actually go through the verification process + + void StatusBar(UINT strID); + void StatusBar(char *status); + void LocalizedMessageBox(UINT msgID, UINT titleID, UINT type=MB_OK); + void AddToList(UINT strID); + void CloseHTTP(); + BOOL InitHTTP(); + void DebugSpew(char *); + void DebugSpew(CString &msg); + int GetHTTPFile(char *remote, char *local); + BOOL ApplyPatch(); + int UpdateTheLauncher(); + void GetHTTPFileErrorBox(int error_id, char *remote, char *local); + BOOL ParseMOTDFile(void); + void DisplayVersions(int maj1, int min1, int bld1, int maj2=-1, int min2=-1, int bld2=-1); + void Cleanup(void); + + CUpdateDlg(CWnd* pParent = NULL, int should_verify = 1); // standard constructor + + CFont m_listfont; // font for the update feedback list + CMessageWindowDlg msg_dlg; + +// Dialog Data + //{{AFX_DATA(CUpdateDlg) + enum { IDD = IDD_UPDATE_DIALOG }; + CLabel m_UserMsgStatic; + CEdit m_LatestVersionEdit; + CEdit m_YourVersionEdit; + CEdit m_MOTDBox; + CProgressCtrl m_progress; + CListBox m_list; + CString m_statusbar; + CString m_usermsg; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CUpdateDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + BOOL GetVersionNfo(); + BOOL GetMOTD(); + + // User's current version + uint UsrMajor, UsrMinor, UsrBuild; + + // Newest version available + uint NewMajor, NewMinor, NewBuild; + + // Generated message map functions + //{{AFX_MSG(CUpdateDlg) + afx_msg void OnYes(); + virtual void OnCancel(); + virtual BOOL OnInitDialog(); + afx_msg void OnClose(); + afx_msg LRESULT OnCommandHelp(WPARAM wParam, LPARAM lParam); + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +extern bool CancelPressed; // indicates that the user has pressed cancel button + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_UPDATEDLG_H__FFEFED62_26D1_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/VerifyA3D.h b/D3Launch/VerifyA3D.h new file mode 100644 index 00000000..17c34daf --- /dev/null +++ b/D3Launch/VerifyA3D.h @@ -0,0 +1,29 @@ +///////////////////////////////////////////////////////////////////////////// +// +// VerifyA3D.h : header file for Aureal A3D verification handling. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef __VERIFYA3D_H +#define __VERIFYA3D_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +// Public verification function. +// Return TRUE if Aureal, FALSE if clone, -1 if check could not succeed. +extern int WINAPI VerifyAurealA3D(void); + +#ifdef __cplusplus +} +#endif + +#endif + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// diff --git a/D3Launch/VideoDetectDlg.cpp b/D3Launch/VideoDetectDlg.cpp new file mode 100644 index 00000000..86877183 --- /dev/null +++ b/D3Launch/VideoDetectDlg.cpp @@ -0,0 +1,95 @@ +// VideoDetectDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "d3launch.h" +#include "VideoDetectDlg.h" +#include "OS_Config.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define DETECT_DIRECT3D 0x01 +#define DETECT_OPENGL 0x02 +#define DETECT_GLIDE 0x04 + + +///////////////////////////////////////////////////////////////////////////// +// CVideoDetectDlg dialog + + +CVideoDetectDlg::CVideoDetectDlg(CWnd* pParent /*=NULL*/) + : CDialog(CVideoDetectDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CVideoDetectDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + DetectDirect3D=TRUE; + DetectOpenGL=TRUE; + DetectGlide=TRUE; +} + + +void CVideoDetectDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CVideoDetectDlg) + DDX_Control(pDX, IDC_OPENGL_CHECK, m_OpenGLCheck); + DDX_Control(pDX, IDC_GLIDE_CHECK, m_GlideCheck); + DDX_Control(pDX, IDC_DIRECT3D_CHECK, m_Direct3DCheck); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CVideoDetectDlg, CDialog) + //{{AFX_MSG_MAP(CVideoDetectDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CVideoDetectDlg message handlers + +void CVideoDetectDlg::OnOK() +{ + // TODO: Add extra validation here + DetectDirect3D=m_Direct3DCheck.GetCheck(); + DetectOpenGL=m_OpenGLCheck.GetCheck(); + DetectGlide=m_GlideCheck.GetCheck(); + + // Store these settings for next time + int settings=0; + if(DetectDirect3D) settings |= DETECT_DIRECT3D; + if(DetectOpenGL) settings |= DETECT_OPENGL; + if(DetectGlide) settings |= DETECT_GLIDE; + os_config_write_uint(szSectionName, "VideoDetectSettings", settings); + + RenderersDetected=TRUE; + + CDialog::OnOK(); +} + +BOOL CVideoDetectDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + int settings; + + // Get the settings from last time user chose + settings=os_config_read_uint(szSectionName, "VideoDetectSettings", DETECT_DIRECT3D|DETECT_GLIDE); + DetectDirect3D=settings & DETECT_DIRECT3D; + DetectOpenGL=settings & DETECT_OPENGL; + DetectGlide=settings & DETECT_GLIDE; + + // Set the check marks appropriately + m_Direct3DCheck.SetCheck(DetectDirect3D); + m_OpenGLCheck.SetCheck(DetectOpenGL); + m_GlideCheck.SetCheck(DetectGlide); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/D3Launch/VideoDetectDlg.h b/D3Launch/VideoDetectDlg.h new file mode 100644 index 00000000..0456dd28 --- /dev/null +++ b/D3Launch/VideoDetectDlg.h @@ -0,0 +1,53 @@ +#if !defined(AFX_VIDEODETECTDLG_H__11362FC3_61E3_11D2_A4E0_00A0C96ED60D__INCLUDED_) +#define AFX_VIDEODETECTDLG_H__11362FC3_61E3_11D2_A4E0_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// VideoDetectDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CVideoDetectDlg dialog + +class CVideoDetectDlg : public CDialog +{ +// Construction +public: + CVideoDetectDlg(CWnd* pParent = NULL); // standard constructor + + int DetectOpenGL; + int DetectDirect3D; + int DetectGlide; + +// Dialog Data + //{{AFX_DATA(CVideoDetectDlg) + enum { IDD = IDD_VIDEODETECT_DLG }; + CButton m_OpenGLCheck; + CButton m_GlideCheck; + CButton m_Direct3DCheck; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CVideoDetectDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CVideoDetectDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_VIDEODETECTDLG_H__11362FC3_61E3_11D2_A4E0_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/VideoTab.cpp b/D3Launch/VideoTab.cpp new file mode 100644 index 00000000..90f247ba --- /dev/null +++ b/D3Launch/VideoTab.cpp @@ -0,0 +1,423 @@ +/* + * $Logfile: /DescentIII/Main/D3Launch/VideoTab.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:56:51 $ + * $Author: kevinb $ + * + * + * + * $Log: not supported by cvs2svn $ + * + * 18 5/19/99 12:29p Nate + * Fixed openGL crash, changed Network speed default, changed OpenGL + * detection to default to unchecked, and removed config file parsing from + * US version + * + * 17 4/26/99 11:38a Nate + * Added warning message for opengl or direct3d renderer selection when + * user has glide as an option. + * + * 16 3/02/99 5:46p Nate + * Lots of little changes/fixes + * + * 15 2/05/99 3:51p Nate + * Added conditional compilation directives for OEM support + * + * 14 10/19/98 9:03a Nate + * Video tab now only auto-detects when "None selected" + * + * 13 10/13/98 3:03p Nate + * More fixes and changes. + * + * 12 10/12/98 7:13p Nate + * Fixed several bugs. + * + * 11 10/10/98 4:05p Nate + * Added detection/scanning window messages + * + * 10 10/08/98 6:23p Nate + * Fixed a few bugs. + * + * 9 9/22/98 3:33p Nate + * Added conditional compiling to help system (can toggle between HTML and + * standard windows help) + * + * 8 9/21/98 5:40p Nate + * Incorporated the new HTML help system + * + * 7 9/02/98 9:48a Nate + * Fixed hardware accelerator display bug in the Speed Tab + * + * 6 9/01/98 7:15p Nate + * Major Revision #2 + * + * 5 8/31/98 6:44p Nate + * Major Revision + * + * 4 8/10/98 10:44a Nate + * Added Language selection support + * + * 3 8/05/98 4:52p Nate + * Added registry reading and writing. + * + * 2 8/05/98 11:54a Nate + * Initial Version + * + * $NoKeywords: $ + */ + +// VideoTab.cpp : implementation file +// + +#include "stdafx.h" +#include "afxpriv.h" +#include "afxext.h" +#include "D3Launch.h" +#include "VideoTab.h" +#include "3D_detect.h" +#include "PsTypes.h" +#include "OS_Config.h" +#include "VideoDetectDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +CVideoTab * CurrentVideoTab = NULL; +BOOL VideoTabInitialized = FALSE; + +///////////////////////////////////////////////////////////////////////////// +// CVideoTab property page + +IMPLEMENT_DYNCREATE(CVideoTab, CPropertyPage) + +CVideoTab::CVideoTab() : CPropertyPage(CVideoTab::IDD) +{ + //{{AFX_DATA_INIT(CVideoTab) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + CurrentVideoTab = NULL; +} + +CVideoTab::~CVideoTab() +{ + CurrentVideoTab = NULL; +} + +int CVideoTab::GetCurrentCard() +{ + int current = m_videocard_list.GetCurSel(); + + if ( (current < 0) || (current>=Num_cards)) { + current = 0; + } + return current; +} + +void CVideoTab::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CVideoTab) + DDX_Control(pDX, IDC_VIDEOCARD_LIST, m_videocard_list); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CVideoTab, CPropertyPage) + //{{AFX_MSG_MAP(CVideoTab) + ON_BN_CLICKED(IDC_VIDEOCARD_DETECT, OnVideocardDetect) + ON_MESSAGE(WM_COMMANDHELP,OnCommandHelp) + ON_WM_HELPINFO() + ON_CBN_SELCHANGE(IDC_VIDEOCARD_LIST, OnSelchangeVideocardList) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CVideoTab message handlers + +extern HINSTANCE Dd_dll_handle; + +void CVideoTab::OnVideocardDetect() +{ + // TODO: Add your control notification handler code here + if(VideoCardsDetected) return; + +#if (!defined(OEM_VOODOO3) || defined(USE_ALL_VIDEO_OPTIONS)) + // Display the scan selection options to user + CVideoDetectDlg dlg; + dlg.DoModal(); +#endif + + // Set the wait cursor + CWaitCursor wc; + + // Clear the box + m_videocard_list.ResetContent(); + + // Display the scanning window + m_MsgDlg.m_ScanningMsg.LoadString(IDS_VIDEOTAB_SCANNING); + m_MsgDlg.m_WaitMsg.LoadString(IDS_PLEASE_WAIT_MSG); + m_MsgDlg.Create(IDD_MSG_DLG,this); + m_MsgDlg.ShowWindow(SW_SHOW); + m_MsgDlg.UpdateData(FALSE); + +#if (defined(OEM_VOODOO3) && !defined(USE_ALL_VIDEO_OPTIONS)) + // Detect only 3dfx cards + detect_3dcards(0,1,0); +#else + // Detect the cards + detect_3dcards(dlg.DetectDirect3D,dlg.DetectGlide,dlg.DetectOpenGL); +#endif + + // Remove the scanning window + m_MsgDlg.DestroyWindow(); + + // Now that the window is gone, release the opengl dll (fixes crash) + if(opengl_dll_handle!=NULL) { + FreeLibrary(opengl_dll_handle); + opengl_dll_handle=NULL; + } + + int i; + int current=0; + + // Add cards to listbox + for (i=0; i2) { + current=0; // set it to "none", make user pick + + CString mtod_msg, mtod_title; + mtod_msg.LoadString(IDS_VIDEOTAB_MTOD_MSG); + mtod_title.LoadString(IDS_VIDEOTAB_MTOD_TITLE); + MessageBox(mtod_msg,mtod_title,MB_OK|MB_ICONINFORMATION); + } + + // Set the determined selection + m_videocard_list.SetCurSel(current); + + // Desensitize detection button since cards have been detected + //HWND hwnd; + //GetDlgItem(IDC_VIDEOCARD_DETECT,&hwnd); + //::EnableWindow(hwnd,FALSE); +} + + +BOOL CVideoTab::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + // TODO: Add extra initialization here + CDialog::OnInitDialog(); + + CurrentVideoTab = this; + + // Get the PreferredRenderer + RendererType renderer_id = (RendererType)os_config_read_uint(NULL, "PreferredRenderer", RENDERER_NONE); + + // Get the name of the selected rendering device + char *current_card = os_config_read_string(szSectionName, "RenderingDeviceName", "" ); + + // Clear the box + m_videocard_list.ResetContent(); + + // if renderer none is selected, automatically display the detection dialog + int current=-1; + if(renderer_id==RENDERER_NONE) { + +#if (!defined(OEM_VOODOO3) || defined(USE_ALL_VIDEO_OPTIONS)) + // Display the scan selection options to user + CVideoDetectDlg dlg; + dlg.DoModal(); +#endif + + // Set the wait cursor + CWaitCursor wc; + + // Display the scanning window + m_MsgDlg.m_ScanningMsg.LoadString(IDS_VIDEOTAB_SCANNING); + m_MsgDlg.m_WaitMsg.LoadString(IDS_PLEASE_WAIT_MSG); + m_MsgDlg.Create(IDD_MSG_DLG,this); + m_MsgDlg.ShowWindow(SW_SHOW); + m_MsgDlg.UpdateData(FALSE); + +#if (defined(OEM_VOODOO3) && !defined(USE_ALL_VIDEO_OPTIONS)) + // Detect only 3dfx cards + detect_3dcards(0,1,0); +#else + // Detect the cards + detect_3dcards(dlg.DetectDirect3D,dlg.DetectGlide,dlg.DetectOpenGL); +#endif + + // Remove the scanning window + m_MsgDlg.DestroyWindow(); + + // Now that the window is gone, release the opengl dll (fixes crash) + if(opengl_dll_handle!=NULL) { + FreeLibrary(opengl_dll_handle); + opengl_dll_handle=NULL; + } + + // Put the detected cards into the list, and see if the selected card is one of them + for(int j=0; j2) { + current=0; // set it to "none", make user pick + + CString mtod_msg, mtod_title; + mtod_msg.LoadString(IDS_VIDEOTAB_MTOD_MSG); + mtod_title.LoadString(IDS_VIDEOTAB_MTOD_TITLE); + MessageBox(mtod_msg,mtod_title,MB_OK|MB_ICONINFORMATION); + } + } + + /* + // If the selected card isn't in the current list, put it in the list + if(current==-1) { + Cards[Num_cards].renderer_type=renderer_id; + strcpy( Cards[Num_cards].name, current_card ); + m_videocard_list.InsertString( Num_cards, GetFullName(&Cards[Num_cards]) ); + current = Num_cards; + Num_cards++; + } + */ + + // Desensitize detection button since cards have been detected + //HWND hwnd; + //GetDlgItem(IDC_VIDEOCARD_DETECT,&hwnd); + //::EnableWindow(hwnd,FALSE); + + /* + detect_3dcards(0); + m_videocard_list.InsertString( 0, GetFullName(&Cards[0]) ); + + if ( renderer_id != RENDERER_NONE ) { + Cards[Num_cards].renderer_type=renderer_id; + strcpy( Cards[Num_cards].name, current_card ); + m_videocard_list.InsertString( Num_cards, GetFullName(&Cards[Num_cards]) ); + current = Num_cards; + Num_cards++; + } + */ + + m_videocard_list.SetCurSel(current); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CVideoTab::OnOK() +{ + // TODO: Add your specialized code here and/or call the base class + int current = m_videocard_list.GetCurSel(); + + if ( (current < 0) || (current>=Num_cards)) { + current = 0; + } + + OutputDebugString("Setting the videocard!\n"); + + // Get the PreferredRenderer + os_config_write_uint(NULL, "PreferredRenderer", Cards[current].renderer_type); + + // Write out the name of the rendering device + os_config_write_string(szSectionName, "RenderingDeviceName", Cards[current].name); + + CPropertyPage::OnOK(); +} + + +BOOL CVideoTab::OnHelpInfo(HELPINFO* pHelpInfo) +{ + // TODO: Add your message handler code here and/or call default + +#ifdef USE_HTML_HELP_SYSTEM + CWaitCursor wc; + help_launch(VIDEOTAB_HELP); + return 1; +#else + return CPropertyPage::OnHelpInfo(pHelpInfo); +#endif +} + +// Display the html help file +afx_msg LRESULT CVideoTab::OnCommandHelp(WPARAM wParam, LPARAM lParam) +{ +#ifdef USE_HTML_HELP_SYSTEM + help_launch(VIDEOTAB_HELP); + return 1; +#else + return CPropertyPage::OnCommandHelp(wParam,lParam); +#endif +} + +void CVideoTab::OnSelchangeVideocardList() +{ + int current = m_videocard_list.GetCurSel(); + + if ( (current < 0) || (current>=Num_cards)) { + current = 0; + } + + // If user's DirectX version is less than 6.0, + // then don't let them select Direct 3D + if(Dx_version<6) { + if(Cards[current].renderer_type==RENDERER_DIRECT3D) { + CString title, msg; + title.LoadString(IDS_VIDEOTAB_DXVERSION_TITLE); + msg.LoadString(IDS_VIDEOTAB_DXVERSION_MSG); + MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); + m_videocard_list.SetCurSel(0); + return; + } + } + + // See if user has the option of selecting 3Dfx glide + int glide = -1; + for(int j=0;j=0 && glide= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// VideoTab.h : header file +// + +#include "MsgDlg.h" + +///////////////////////////////////////////////////////////////////////////// +// CVideoTab dialog + +class CVideoTab : public CPropertyPage +{ + DECLARE_DYNCREATE(CVideoTab) + +// Construction +public: + CVideoTab(); + ~CVideoTab(); + + int GetCurrentCard(); + CMsgDlg m_MsgDlg; + +// Dialog Data + //{{AFX_DATA(CVideoTab) + enum { IDD = IDD_PROPPAGE_VIDEO }; + CComboBox m_videocard_list; + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CVideoTab) + public: + virtual void OnOK(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CVideoTab) + afx_msg void OnVideocardDetect(); + virtual BOOL OnInitDialog(); + afx_msg LRESULT OnCommandHelp(WPARAM wParam, LPARAM lParam); + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); + afx_msg void OnSelchangeVideocardList(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +extern CVideoTab * CurrentVideoTab; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_VIDEOTAB_H__78170D82_2215_11D2_8CBD_00A0C96ED60D__INCLUDED_) diff --git a/D3Launch/eax.h b/D3Launch/eax.h new file mode 100644 index 00000000..8609f206 --- /dev/null +++ b/D3Launch/eax.h @@ -0,0 +1,99 @@ + +// EAX.H -- DirectSound Environmental Audio Extensions + +#ifndef EAX_H_INCLUDED +#define EAX_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + +// EAX (listener) reverb property set {4a4e6fc1-c341-11d1-b73a-444553540000} +DEFINE_GUID(DSPROPSETID_EAX_ReverbProperties, + 0x4a4e6fc1, + 0xc341, + 0x11d1, + 0xb7, 0x3a, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00); + +typedef enum +{ + DSPROPERTY_EAX_ALL, // all reverb properties + DSPROPERTY_EAX_ENVIRONMENT, // standard environment no. + DSPROPERTY_EAX_VOLUME, // loudness of the reverb + DSPROPERTY_EAX_DECAYTIME, // how long the reverb lasts + DSPROPERTY_EAX_DAMPING // the high frequencies decay faster +} DSPROPERTY_EAX_REVERBPROPERTY; + +#define EAX_NUM_STANDARD_PROPERTIES (DSPROPERTY_EAX_DAMPING + 1) + +// use this structure for get/set all properties... +typedef struct +{ + unsigned long environment; // 0 to EAX_ENVIRONMENT_COUNT-1 + float fVolume; // 0 to 1 + float fDecayTime_sec; // seconds, 0.1 to 100 + float fDamping; // 0 to 1 +} EAX_REVERBPROPERTIES; + + +//#define EAX_MAX_ENVIRONMENT (EAX_ENVIRONMENT_COUNT - 1) + +// presets +#define EAX_PRESET_GENERIC EAX_ENVIRONMENT_GENERIC,0.5F,1.493F,0.5F +#define EAX_PRESET_PADDEDCELL EAX_ENVIRONMENT_PADDEDCELL,0.25F,0.1F,0.0F +#define EAX_PRESET_ROOM EAX_ENVIRONMENT_ROOM,0.417F,0.4F,0.666F +#define EAX_PRESET_BATHROOM EAX_ENVIRONMENT_BATHROOM,0.653F,1.499F,0.166F +#define EAX_PRESET_LIVINGROOM EAX_ENVIRONMENT_LIVINGROOM,0.208F,0.478F,0.0F +#define EAX_PRESET_STONEROOM EAX_ENVIRONMENT_STONEROOM,0.5F,2.309F,0.888F +#define EAX_PRESET_AUDITORIUM EAX_ENVIRONMENT_AUDITORIUM,0.403F,4.279F,0.5F +#define EAX_PRESET_CONCERTHALL EAX_ENVIRONMENT_CONCERTHALL,0.5F,3.961F,0.5F +#define EAX_PRESET_CAVE EAX_ENVIRONMENT_CAVE,0.5F,2.886F,1.304F +#define EAX_PRESET_ARENA EAX_ENVIRONMENT_ARENA,0.361F,7.284F,0.332F +#define EAX_PRESET_HANGAR EAX_ENVIRONMENT_HANGAR,0.5F,10.0F,0.3F +#define EAX_PRESET_CARPETEDHALLWAY EAX_ENVIRONMENT_CARPETEDHALLWAY,0.153F,0.259F,2.0F +#define EAX_PRESET_HALLWAY EAX_ENVIRONMENT_HALLWAY,0.361F,1.493F,0.0F +#define EAX_PRESET_STONECORRIDOR EAX_ENVIRONMENT_STONECORRIDOR,0.444F,2.697F,0.638F +#define EAX_PRESET_ALLEY EAX_ENVIRONMENT_ALLEY,0.25F,1.752F,0.776F +#define EAX_PRESET_FOREST EAX_ENVIRONMENT_FOREST,0.111F,3.145F,0.472F +#define EAX_PRESET_CITY EAX_ENVIRONMENT_CITY,0.111F,2.767F,0.224F +#define EAX_PRESET_MOUNTAINS EAX_ENVIRONMENT_MOUNTAINS,0.194F,7.841F,0.472F +#define EAX_PRESET_QUARRY EAX_ENVIRONMENT_QUARRY,1.0F,1.499F,0.5F +#define EAX_PRESET_PLAIN EAX_ENVIRONMENT_PLAIN,0.097F,2.767F,0.224F +#define EAX_PRESET_PARKINGLOT EAX_ENVIRONMENT_PARKINGLOT,0.208F,1.652F,1.5F +#define EAX_PRESET_SEWERPIPE EAX_ENVIRONMENT_SEWERPIPE,0.652F,2.886F,0.25F +#define EAX_PRESET_UNDERWATER EAX_ENVIRONMENT_UNDERWATER,1.0F,1.499F,0.0F +#define EAX_PRESET_DRUGGED EAX_ENVIRONMENT_DRUGGED,0.875F,8.392F,1.388F +#define EAX_PRESET_DIZZY EAX_ENVIRONMENT_DIZZY,0.139F,17.234F,0.666F +#define EAX_PRESET_PSYCHOTIC EAX_ENVIRONMENT_PSYCHOTIC,0.486F,7.563F,0.806F + + +// EAX buffer reverb property set {4a4e6fc0-c341-11d1-b73a-444553540000} +DEFINE_GUID(DSPROPSETID_EAXBUFFER_ReverbProperties, + 0x4a4e6fc0, + 0xc341, + 0x11d1, + 0xb7, 0x3a, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00); + +typedef enum +{ + DSPROPERTY_EAXBUFFER_ALL, // all reverb buffer properties + DSPROPERTY_EAXBUFFER_REVERBMIX // the wet source amount +} DSPROPERTY_EAXBUFFER_REVERBPROPERTY; + +// use this structure for get/set all properties... +typedef struct +{ + float fMix; // linear factor, 0.0F to 1.0F +} EAXBUFFER_REVERBPROPERTIES; + +#define EAX_REVERBMIX_USEDISTANCE -1.0F // out of normal range + // signifies the reverb engine should + // calculate it's own reverb mix value + // based on distance + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif diff --git a/D3Launch/hlp/AfxDlg.rtf b/D3Launch/hlp/AfxDlg.rtf new file mode 100644 index 00000000..c6e400b9 --- /dev/null +++ b/D3Launch/hlp/AfxDlg.rtf @@ -0,0 +1,215 @@ +{\rtf1\ansi\ansicpg1252\uc1 \deff0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f3\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;} +{\f5\fswiss\fcharset0\fprq2{\*\panose 00000000000000000000}Helvetica{\*\falt Arial};}{\f9\fswiss\fcharset0\fprq2{\*\panose 00000000000000000000}Helv{\*\falt Arial};}{\f11\fswiss\fcharset0\fprq2{\*\panose 00000000000000000000}MS Sans Serif;}} +{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0; +\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{\nowidctlpar\adjustright \fs20 \snext0 Normal;}{\s1\sb240\nowidctlpar\adjustright \b\f9\ul \sbasedon0 \snext0 heading 1;}{ +\s2\sb120\nowidctlpar\adjustright \b\f9 \sbasedon0 \snext0 heading 2;}{\s3\li360\nowidctlpar\adjustright \b \sbasedon0 \snext17 heading 3;}{\s4\li360\nowidctlpar\adjustright \ul \sbasedon0 \snext17 heading 4;}{\s5\li720\nowidctlpar\adjustright \b\fs20 +\sbasedon0 \snext17 heading 5;}{\s6\li720\nowidctlpar\adjustright \fs20\ul \sbasedon0 \snext17 heading 6;}{\s7\li720\nowidctlpar\adjustright \i\fs20 \sbasedon0 \snext17 heading 7;}{\s8\li720\nowidctlpar\adjustright \i\fs20 \sbasedon0 \snext17 heading 8;}{ +\s9\li720\nowidctlpar\adjustright \i\fs20 \sbasedon0 \snext17 heading 9;}{\*\cs10 \additive Default Paragraph Font;}{\*\cs15 \additive \fs16\up6\lang1033 \sbasedon10 footnote reference;}{\s16\nowidctlpar\adjustright \fs20 \sbasedon0 \snext16 +footnote text;}{\s17\li720\nowidctlpar\adjustright \fs20 \sbasedon0 \snext17 Normal Indent;}{\s18\fi-240\li480\sb80\nowidctlpar\tx480\adjustright \f5 \sbasedon0 \snext18 nscba;}{\s19\fi-240\li240\sa20\nowidctlpar\adjustright \f5 \sbasedon0 \snext19 j;}{ +\s20\li480\sa20\nowidctlpar\adjustright \f5 \sbasedon0 \snext20 ij;}{\s21\sb80\sa20\nowidctlpar\adjustright \f5 \sbasedon0 \snext21 btb;}{\s22\fi-240\li2400\sb20\sa20\nowidctlpar\adjustright \f5\fs20 \sbasedon0 \snext22 ctcb;}{ +\s23\fi-240\li480\sa40\nowidctlpar\tx480\adjustright \f5 \sbasedon0 \snext23 ns;}{\s24\sa120\nowidctlpar\adjustright \f5\fs28 \sbasedon0 \snext24 TT;}{\s25\fi-240\li2400\sa20\nowidctlpar\adjustright \f5 \sbasedon0 \snext25 crtj;}{ +\s26\fi-240\li480\nowidctlpar\tx480\adjustright \f5 \sbasedon0 \snext26 nsca;}{\s27\sa20\nowidctlpar\adjustright \f5 \sbasedon0 \snext27 bt;}{\s28\li240\sb120\sa40\nowidctlpar\adjustright \f5 \sbasedon0 \snext28 Hf;}{ +\s29\li240\sb120\sa40\nowidctlpar\adjustright \f5 \sbasedon0 \snext29 Hs;}{\s30\li480\sb120\sa40\nowidctlpar\adjustright \f5 \sbasedon0 \snext30 RT;}{\s31\fi-2160\li2160\sb240\sa80\nowidctlpar\tx2160\adjustright \f5 \sbasedon0 \snext31 c;}{ +\s32\li2160\sa20\nowidctlpar\adjustright \f5 \sbasedon0 \snext32 ct;}{\s33\li240\sa20\nowidctlpar\adjustright \f5 \sbasedon0 \snext33 it;}{\s34\li480\nowidctlpar\adjustright \f5\fs20 \sbasedon0 \snext34 nsct;}{ +\s35\fi-160\li400\sb80\sa40\nowidctlpar\adjustright \f5 \sbasedon0 \snext35 nscb;}{\s36\fi-2640\li2880\sb120\sa40\nowidctlpar\brdrb\brdrs\brdrw15 \brdrbtw\brdrs\brdrw15 \tx2880\adjustright \f5 \sbasedon0 \snext36 HC2;}{ +\s37\fi-2640\li2880\sb120\sa20\nowidctlpar\tx2880\adjustright \f5 \sbasedon0 \snext37 C2;}{\s38\fi-240\li2400\sa20\nowidctlpar\adjustright \f5\fs20 \sbasedon0 \snext38 ctc;}{\s39\li2160\sb160\nowidctlpar\adjustright \f5 \sbasedon0 \snext39 crt;}{ +\s40\li480\sb20\sa40\nowidctlpar\adjustright \f5 \sbasedon0 \snext40 or;}{\s41\fi-259\li360\sb40\sa40\nowidctlpar\tx360\adjustright \f11\fs20 \sbasedon0 \snext41 Ln1;}{\s42\li115\sb80\sa80\nowidctlpar\adjustright \f11\fs20 \sbasedon0 \snext0 *Intro;}{ +\s43\li115\sb80\sa80\keepn\nowidctlpar\adjustright \b\f11 \sbasedon3 \snext42 *Title;}{\s44\fi-245\li360\sb80\nowidctlpar\adjustright \f11\fs20 \snext44 *Jl;}{\s45\li360\sb40\sa40\nowidctlpar\adjustright \f11\fs20 \snext0 Lp1;}{ +\s46\fi-1800\li1915\sb60\sl-240\slmult0\nowidctlpar\tx1915\adjustright \f11\fs20 \sbasedon0 \snext46 Tph;}{\s47\li115\sb120\sa80\nowidctlpar\adjustright \b\f11\fs20 \snext41 Proch;}{\*\cs48 \additive \super \sbasedon10 endnote reference;}}{\*\listtable +{\list\listtemplateid67698689\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid249584757} +{\list\listtemplateid67698689\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid656416521} +{\list\listtemplateid67698703\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1365445431}{\list\listtemplateid67698689 +\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1747218252}{\list\listtemplateid67698689\listsimple +{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1832672824}}{\*\listoverridetable{\listoverride\listid656416521 +\listoverridecount0\ls1}{\listoverride\listid1832672824\listoverridecount0\ls2}{\listoverride\listid1365445431\listoverridecount0\ls3}{\listoverride\listid1747218252\listoverridecount0\ls4}{\listoverride\listid249584757\listoverridecount0\ls5}}{\info +{\title # Descent 3 Help Index}{\author David Broman}{\operator Nate Goudie}{\creatim\yr1999\mo5\dy22\hr1\min24}{\revtim\yr1999\mo5\dy22\hr1\min24}{\version2}{\edmins2}{\nofpages12}{\nofwords108}{\nofchars617}{\*\company Dell Computer Corporation} +{\nofcharsws0}{\vern89}}\widowctrl\ftnbj\aenddoc\hyphcaps0\viewkind4\viewscale100 \fet0\sectd \linex0\endnhere\sectdefaultcl {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}} +{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (} +{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain +\s2\sb120\sa120\keepn\nowidctlpar\outlinelevel1\adjustright \b\f9 {\cs15\b0\fs20\up6 #{\footnote \pard\plain \sl240\slmult0\widctlpar\adjustright \fs20 {\cs15\fs16\up6 #}{ HIDD_D3LAUNCH_DIALOG}}}{\b0\fs20 }{\cs15\b0\fs20\up6 K{\footnote \pard\plain +\s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 K}{ Main menu}}}{\b0\fs20 }{\cs15\b0\fs20\up6 ${\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 $}{ Main Launcher Menu}}}{\fs28 Main Launcher Window}{ +\par }\pard\plain \widctlpar\adjustright \fs20 {\f9 +\par Welcome to the main menu of the Descent 3 Launcher! From here, you can play Descent 3, configure your game settings, view related information, and even automatically update your version of Descent 3 to the newest available version. +\par +\par The following buttons allow you to access these different features: +\par +\par }{\b\f9 Play +\par }{\f9 Pressing the Play button will launch Descent 3. Make sure you have configured your game from Setup before pressing the Play button! +\par }\pard\plain \s16\widctlpar\adjustright \fs20 {\f9 +\par }\pard\plain \widctlpar\adjustright \fs20 {\b\f9 Setup +\par }{\f9 The Setup button takes you to the }{\f9\uldb Setup Window}{\v\f9 HIDD_SETUP_DIALOG}{\f9 where you can configure your options for Descent 3. +\par }{\f9\uldb +\par }\pard\plain \s16\widctlpar\adjustright \fs20 {\b\f9 Auto-Update}{ +\par }\pard\plain \widctlpar\adjustright \fs20 {\f9 The Auto-Update button takes you to the }{\f9\uldb Auto-Update Window}{\v\f9 HIDD_UPDATE_DIALOG}{\f9 where you can update your copy of Descent 3 to the newest available version. +\par +\par }{\b\f9 View ReadMe +\par }{\f9 Pressing the ReadMe button will cause the ReadMe Viewer to be displayed. The ReadMe files contain important game-related information, so it is a good idea to check them out. +\par +\par }{\b\f9 Install Drivers +\par }{\f9 The Install Drivers button will display the }{\f9\uldb Driver Installation Menu}{\v\f9 HIDD_DRIVERS_DIALOG}{\f9 where you can install DirectX and other drivers. +\par +\par }{\b\f9 Visit Us! +\par }{\f9 This button will take you to the Outrage Entertainment Web Page where you can learn more about the people who brought you Descent 3. +\par +\par }{\b\f9 Play D3 Online! +\par }{\f9 The PXO button will take you to the Parallax Online Web page. Parallax Online allows you to play multi-player Descent 3 for free over the internet. +\par +\par }\pard \sb120\sa120\keepn\nowidctlpar\adjustright {\f9 \page }{\cs15\f9\fs16\up6 #{\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 #}{ HIDD_UPDATE_DIALOG}}}{\f9 }{\cs15\f9\fs16\up6 K{\footnote \pard\plain +\s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 K}{ update;patch}}}{\f9 }{\cs15\f9\fs16\up6 ${\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 $}{ Auto-Update Window}}}{\b\f9\fs28 Auto-Update Window +\par }\pard \widctlpar\adjustright {\b\f9\fs24 +\par }{\f9 The Auto-Update window allows you to automatically update your copy of Descent 3 to the latest version by downloading an update patch from the Internet. +\par +\par }{\b\f9 The Message of the Day +\par }{\f9 At the top of the window is the Message of the Day, which displays information regarding new versions or other items of interest. +\par +\par }{\b\f9 Version Number Display +\par }{\f9 This display allows you to easily compare your version of Descent 3 with the newest version currently available. +\par +\par }{\b\f9 Status Window and Messages +\par }{\f9 The status window and messages are initially used to inform you when there is a new version of Descent 3 available for download. +\par +\par If a new version is available, you can download the patch and apply it by pressing OK. +\par +\par Once you press OK, the }{\f9\uldb Site Selection Window}{\v\f9 HIDD_SITE_SELECTION_DIALOG}{\f9 will appear. Choose the site +you wish to download the patch from and the download will begin. Once the patch has finished downloading, it will automatically start apply the patch to your copy of Descent 3. +\par +\par After the patch has completed, you will receive a message stating that the pa +tch was successful. Most of the time, the launcher will need to be updated as well. After you click OK on the Auto-Update window, you will be notified if this is the case. The launcher will then shut down, update itself, and restart. +\par +\par }\pard \sb120\sa120\keepn\nowidctlpar\adjustright {\f9 \page }{\cs15\f9\fs16\up6 #{\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 #}{ HIDD_PROPPAGE_DIRECTX}}}{\f9 }{\cs15\f9\fs16\up6 K{\footnote \pard\plain +\s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 K}{ directx}}}{\f9 }{\cs15\f9\fs16\up6 ${\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 $}{ DirectX Setup}}}{\b\f9\fs28 DirectX Setup +\par }\pard \widctlpar\adjustright {\f9 +\par The DirectX Setup displays the current version of DirectX installed on your system. +\par +\par The status box will let you know if your version of DirectX is sufficient to play Descent 3. Descent 3 generally requires DirectX 6.1, though under some circumstances you may be able to play with versions as old as DirectX 3.0. If you are playing under W +indows 95/98, it is recommended that you install DirectX 6.1 on your system. DirectX 6.1 is not supported under Windows NT. +\par +\par The button at the bottom of the DirectX Window will take you directly to the Microsoft DirectX download page. +\par +\par }\pard \sb120\sa120\keepn\nowidctlpar\adjustright {\f9 \page }{\cs15\f9\fs16\up6 #{\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 #}{ HIDD_PROPPAGE_VIDEO}}}{\f9 }{\cs15\f9\fs16\up6 K{\footnote \pard\plain +\s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 K}{ video}}}{\f9 }{\cs15\f9\fs16\up6 ${\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 $}{ Video Setup}}}{\b\f9\fs28 Video Setup +\par }\pard \widctlpar\adjustright {\f9 +\par The Video setup window displays the currently-selected rendering device. +\par +\par Descent 3 supports three types of renderers (known as APIs): 3Dfx Glide, Direct3D, and OpenGL. A hardware accelerated 3D card is required to play Descent 3. +\par +\par The button at the bottom of the window will allow you to redetect certain devices and select a new renderer. +\par +\par }{\b\f9 IMPORTANT: +\par You must make sure that you have installed all the latest drivers for your video card(s). +\par }{\f9 +\par Also, some systems may + experience problems when attempting to detect more than one type of device from the Video Selection Dialog at the same time. If this occurs, try selecting only the renderer you wish to use (i.e. Glide, Direct3D, or OpenGL). Finally, if you do not have +a Voodoo Graphics card, it is recommended that you disable the option to detect Glide since this has been known to cause problems on a few systems. +\par +\par }\pard \sb120\sa120\keepn\nowidctlpar\adjustright {\f9 \page }{\cs15\f9\fs16\up6 #{\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 #}{ HIDD_PROPPAGE_AUDIO}}}{\f9 }{\cs15\f9\fs16\up6 K{\footnote \pard\plain +\s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 K}{ audio}}}{\f9 }{\cs15\f9\fs16\up6 ${\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 $}{ Audio Setup}}}{\b\f9\fs28 Audio Setup +\par }\pard \widctlpar\adjustright {\f9 +\par The Audio Setup allows you to select both an audio playback device and a mixer. +\par +\par }{\b\f9 Current Sound Device and Mixers +\par }{\f9 To enable sound in Descent 3, select a sound device from the pull-down menu. Choose a device that supports at least one sound mixer. +\par +\par Once you have chosen an appropriate sound device, choose one of the available mixers for that device. The possible choices are: +\par +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls5\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls5\adjustright {\b\f9 Software}{\f9 \endash + Uses the CPU to mix all sounds. This is recommended for high end machines with an ample supply of RAM. +\par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f9 +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls5\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls5\adjustright {\b\f9 DirectSound }{\f9 \endash + Uses DirectSound for all sound mixing. This may provide better performance on low-end machines with minimal amounts of RAM. +\par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f9 +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls5\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls5\adjustright {\b\f9 DirectSound 3D}{\f9 \endash + Uses DirectSound 3D to take advantage of the 3D-positional capabilities of your sound card. +\par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f9 +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls5\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls5\adjustright {\b\f9 Aureal 3D}{\f9 \endash +Uses Aureal Vortex Technology (if your card supports it) to implement advanced 3D audio effects. +\par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f9 +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls5\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls5\adjustright {\b\f9 Creative EAX}{\f9 \endash + Uses Creative EAX Technology (if your cards supports it) to take advantage of advanced 3D audio effects. +\par }\pard \sb120\sa120\keepn\nowidctlpar\adjustright {\f9 \page }{\cs15\f9\fs16\up6 #{\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 #}{ HIDD_PROPPAGE_JOYSTICK}}}{\f9 }{\cs15\f9\fs16\up6 K{\footnote \pard\plain +\s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 K}{ controls;joystick}}}{\f9 }{\cs15\f9\fs16\up6 ${\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 $}{ Controls Setup}}}{\b\f9\fs28 Controls Setup +\par }\pard \widctlpar\adjustright {\f9 +\par This window displays your currently selected game controller. +\par +\par The Enable Force Feedback button allows you to disable force feedback for controllers that support it. +\par +\par The Enable CH Flightstick Pro Mode button allows you to enable special handling of a CH Flightstick Pro within Descent 3. Only check this button if you are using a CH Flightstick Pro! +\par +\par The Enable Logitech Mouseman Mode button allows you to enable special handling of a Logitech Mouseman within Descent 3. Only check this button if you are using a Logitech Mouseman! +\par +\par If you want to check or calibrate your controller, click on the Joystick Calibration / Setting button to invoke the Windows Game Controllers dialog. +\par +\par If you change your current controller, click on the Redetect Current Joystick button to read the new settings from Windows. +\par +\par }\pard \sb120\sa120\keepn\nowidctlpar\adjustright {\f9 \page }{\cs15\f9\fs16\up6 #{\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 #}{ HIDD_PROPPAGE_SPEED}}}{\f9 }{\cs15\f9\fs16\up6 K{\footnote \pard\plain +\s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 K}{ speed;detail}}}{\f9 }{\cs15\f9\fs16\up6 ${\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 $}{ Speed Setup}}}{\b\f9\fs28 Speed Setup +\par }\pard \widctlpar\adjustright {\f9 +\par The Speed Setup window allows you to specify a default detail level for your system. +\par +\par You can manually choose a setting from the pull-down list box, or you can press the button at the bottom of the window to have Setup choose one for you, based upon your system properties. +\par +\par Once inside the game, you can custom tailor each of the various detail level settings as you see fit. +\par +\par }\pard \sb120\sa120\keepn\nowidctlpar\adjustright {\f9 \page }{\cs15\f9\fs16\up6 #{\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 #}{ HIDD_PROPPAGE_NETWORK}}}{\f9 }{\cs15\f9\fs16\up6 K{\footnote \pard\plain +\s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 K}{ network}}}{\f9 }{\cs15\f9\fs16\up6 ${\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 $}{ Network Setup}}}{\b\f9\fs28 Network Setup +\par }\pard \widctlpar\adjustright {\f9 +\par The Network Setup window allows you to specify your network connection type and speed. This information is used only in multiplayer. +\par +\par }{\b\f9 IMPORTANT: +\par Inaccurate network settings will hinder performance. Choose the settings that most accurately describe your connection. +\par +\par }{\f9 +\par }\pard \sb120\sa120\keepn\nowidctlpar\adjustright {\f9 \page }{\cs15\f9\fs16\up6 #{\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 #}{ HIDD_PROPPAGE_KEYBOARD}}}{\f9 }{\cs15\f9\fs16\up6 K{\footnote \pard\plain +\s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 K}{ miscellaneous}}}{\f9 }{\cs15\f9\fs16\up6 ${\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 $}{ Miscellaneous Setup}}}{\b\f9\fs28 Miscellaneous Setup +\par }\pard \widctlpar\adjustright {\b\f9 +\par Language +\par }{\f9 This window allows you to select the language for the game. +\par +\par }{\b\f9 Keyboard Type +\par }{\f9 This window allows you to specify the type of keyboard you are using. +\par +\par }{\b\f9 Performance Options +\par }{\f9 Use this checkbox to disable FindFast before playing Descent 3. FindFast is a program that can have a negative effect on the performance of Descent 3 and we STRONGLY recommend that you not run FindFast while playing Descent 3. +\par +\par }{\b\f9 Option D3 Command Line +\par }{\f9 Use this box to enter Descent 3 command-line parameters. You will most likely want to leave this field empty. See the Readme file for a list of command-line options. +\par +\par }\pard \sb120\sa120\keepn\nowidctlpar\adjustright {\f9 \page }{\cs15\f9\fs16\up6 #{\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 #}{ HIDD_SITE_SELECTION_DIALOG}}}{\f9 }{\cs15\f9\fs16\up6 K{\footnote \pard\plain +\s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 K}{ site;select;selection}}}{\f9 }{\cs15\f9\fs16\up6 ${\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 $}{ Site Selection Window}}}{\b\f9\fs28 Site Selection Window +\par }\pard \widctlpar\adjustright {\f9 +\par The site selection window allows you to choose an Internet site from which to download the Descent 3 patch. Any site listed should work, though you should try to choose one close to your location. If one site does not work, try another. +\par +\par Select a site and click OK. +\par +\par }\pard \sb120\sa120\keepn\nowidctlpar\adjustright {\f9 \page }{\cs15\f9\fs16\up6 #{\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 #}{ HIDD_SETUP_DIALOG}}}{\f9 }{\cs15\f9\fs16\up6 K{\footnote \pard\plain +\s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 K}{ Setup}}}{\f9 }{\cs15\f9\fs16\up6 ${\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 $}{ Setup Window}}}{\b\f9\fs28 Setup Window}{\fs28 +\par }\pard \widctlpar\adjustright {\f9 +\par The Setup Window allows you to configure your Descent 3 options. +\par +\par It contains the following sections: +\par +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls4\adjustright {\f9\uldb DirectX}{\v\f9\uldb +HIDD_PROPPAGE_DIRECTX}{\f9\uldb +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls4\adjustright {\f9\uldb Video}{\v\f9\uldb +HIDD_PROPPAGE_VIDEO}{\f9\uldb +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls4\adjustright {\f9\uldb Audio}{\v\f9\uldb +HIDD_PROPPAGE_AUDIO}{\f9\uldb +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls4\adjustright {\f9\uldb Controls}{\v\f9\uldb +HIDD_PROPPAGE_JOYSTICK}{\f9\uldb +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls4\adjustright {\f9\uldb Network}{\v\f9\uldb +HIDD_PROPPAGE_NETWORK}{\f9\uldb +\par {\pntext\pard\plain\f3\fs20 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls4\adjustright {\f9\uldb Misc}{\v\f9\uldb +HIDD_PROPPAGE_KEYBOARD}{\f9\uldb +\par }\pard \widctlpar\adjustright {\f9 +\par }\pard \sb120\sa120\keepn\nowidctlpar\adjustright {\f9 \page }{\cs15\f9\fs16\up6 #{\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 #}{ HIDD_DRIVERS_DIALOG}}}{\f9 }{\cs15\f9\fs16\up6 K{\footnote \pard\plain +\s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 K}{ driver;drivers}}}{\f9 }{\cs15\f9\fs16\up6 ${\footnote \pard\plain \s16\nowidctlpar\adjustright \fs20 {\cs15\fs16\up6 $}{ Driver Installation Menu}}}{\b\f9\fs28 Driver Installation Menu +\par }\pard \widctlpar\adjustright {\f9 +\par The Driver Installation Menu allows you to install various drivers onto your machine. +\par +\par }{\b\f9 Install Microsoft DirectX 6.1 +\par }{\f9 Installs Microsoft DirectX 6.1. +\par +\par }{\b\f9 Install OpenGL with GLSetup +\par }{\f9 Installs the latest OpenGL drivers onto your machine. +\par }{ +\par }} \ No newline at end of file diff --git a/D3Launch/hlp/D3L_hlp1.htm b/D3Launch/hlp/D3L_hlp1.htm new file mode 100644 index 00000000..8e67a129 --- /dev/null +++ b/D3Launch/hlp/D3L_hlp1.htm @@ -0,0 +1,21 @@ + + + + + + +D3 Launcher Help (Main Menu) + + + + +

Descent 3 Launcher Menu Help

+ +
+ +

This is the help file for the Descent 3 Launcher Menu.

+ + diff --git a/D3Launch/hlp/D3L_hlp2.htm b/D3Launch/hlp/D3L_hlp2.htm new file mode 100644 index 00000000..214d9185 --- /dev/null +++ b/D3Launch/hlp/D3L_hlp2.htm @@ -0,0 +1,21 @@ + + + + + + +D3 Launcher Help (Auto-Update) + + + + +

Descent 3 Auto-Update Help

+ +
+ +

This is the help file for the Descent 3 Auto-Update system.

+ + diff --git a/D3Launch/hlp/D3L_hlp3.htm b/D3Launch/hlp/D3L_hlp3.htm new file mode 100644 index 00000000..11412a0e --- /dev/null +++ b/D3Launch/hlp/D3L_hlp3.htm @@ -0,0 +1,22 @@ + + + + + + +D3 Launcher Help (DirectX Setup) + + + + +

Descent 3 DirectX Setup Help

+ +
+ +

This is the help file for the DirectX Setup Tab of the Descent +3 Launcher.

+ + diff --git a/D3Launch/hlp/D3L_hlp4.htm b/D3Launch/hlp/D3L_hlp4.htm new file mode 100644 index 00000000..39f64629 --- /dev/null +++ b/D3Launch/hlp/D3L_hlp4.htm @@ -0,0 +1,22 @@ + + + + + + +D3 Launcher Help (Video Setup) + + + + +

Descent 3 Video Setup Help

+ +
+ +

This is the help file for the Video Setup Tab of the Descent 3 +Launcher.

+ + diff --git a/D3Launch/hlp/D3L_hlp5.htm b/D3Launch/hlp/D3L_hlp5.htm new file mode 100644 index 00000000..311c06cc --- /dev/null +++ b/D3Launch/hlp/D3L_hlp5.htm @@ -0,0 +1,30 @@ + + + + + + +D3 Launcher Help (Audio Setup) + + + + +

Descent 3 Audio Setup

+ +
+ +

This is the help file for the Audio Setup Tab of the Descent 3 +Launcher.

+ +

The following mixers are available for your selection:

+ +
    +
  • Software
  • +
  • DirectSound (8 bit)
  • +
  • DirectSound (16 bit)
  • +
+ + diff --git a/D3Launch/hlp/D3L_hlp6.htm b/D3Launch/hlp/D3L_hlp6.htm new file mode 100644 index 00000000..7de6b0e3 --- /dev/null +++ b/D3Launch/hlp/D3L_hlp6.htm @@ -0,0 +1,22 @@ + + + + + + +D3 Launcher Help (Joystick Setup) + + + + +

Descent 3 Joystick Setup Help

+ +
+ +

This is the help file for the Joystick Setup Tab of the +Descent 3 Launcher.

+ + diff --git a/D3Launch/hlp/D3L_hlp7.htm b/D3Launch/hlp/D3L_hlp7.htm new file mode 100644 index 00000000..cfbf5018 --- /dev/null +++ b/D3Launch/hlp/D3L_hlp7.htm @@ -0,0 +1,22 @@ + + + + + + +D3 Launcher Help (Speed Setup) + + + + +

Descent 3 Speed/Detail Setup

+ +
+ +

This is the help file for the Speed Setup Tab of the Descent 3 +Launcher.

+ + diff --git a/D3Launch/hlp/D3L_hlp8.htm b/D3Launch/hlp/D3L_hlp8.htm new file mode 100644 index 00000000..74c972fa --- /dev/null +++ b/D3Launch/hlp/D3L_hlp8.htm @@ -0,0 +1,22 @@ + + + + + + +D3 Launcher Help (Network Setup) + + + + +

Descent 3 Network Setup Help

+ +
+ +

This is the help file for the Network Setup Tab of the Descent +3 Launcher.

+ + diff --git a/D3Launch/hlp/D3L_hlp9.htm b/D3Launch/hlp/D3L_hlp9.htm new file mode 100644 index 00000000..5e8116b3 --- /dev/null +++ b/D3Launch/hlp/D3L_hlp9.htm @@ -0,0 +1,22 @@ + + + + + + +D3 Launcher Help (Keyboard Setup) + + + + +

Descent 3 Keyboard Setup Help

+ +
+ +

This is the help file for the Keyboard Setup Tab of the +Descent 3 Launcher.

+ + diff --git a/D3Launch/hlp/D3Launch.cnt b/D3Launch/hlp/D3Launch.cnt new file mode 100644 index 00000000..3e904b79 --- /dev/null +++ b/D3Launch/hlp/D3Launch.cnt @@ -0,0 +1,3 @@ +:Base Descent 3.hlp>main +1 Descent 3 Help +2 Descent 3 Launcher=HIDD_D3LAUNCH_DIALOG diff --git a/D3Launch/hlp/D3Launch.hpj b/D3Launch/hlp/D3Launch.hpj new file mode 100644 index 00000000..5c3e2009 --- /dev/null +++ b/D3Launch/hlp/D3Launch.hpj @@ -0,0 +1,63 @@ +; This file is maintained by HCW. Do not modify this file directly. + +[OPTIONS] +COMPRESS=60 Hall Zeck +ERRORLOG=D3Launch.LOG +LCID=0x409 0x0 0x0 ; English (United States) +REPORT=Yes +TITLE=Descent 3 Help +BMROOT=.. +BMROOT=. +ROOT=.. +ROOT=. +HLP=D3Launch.hlp + +[FILES] +afxdlg.rtf + +[ALIAS] +HIDD_ABOUTBOX = HID_APP_ABOUT +HID_HT_SIZE = HID_SC_SIZE +HID_HT_HSCROLL = scrollbars +HID_HT_VSCROLL = scrollbars +HID_HT_MINBUTTON = HID_SC_MINIMIZE +HID_HT_MAXBUTTON = HID_SC_MAXIMIZE +AFX_HIDP_INVALID_FILENAME = AFX_HIDP_default +AFX_HIDP_FAILED_TO_OPEN_DOC = AFX_HIDP_default +AFX_HIDP_FAILED_TO_SAVE_DOC = AFX_HIDP_default +AFX_HIDP_ASK_TO_SAVE = AFX_HIDP_default +AFX_HIDP_FAILED_TO_CREATE_DOC = AFX_HIDP_default +AFX_HIDP_FILE_TOO_LARGE = AFX_HIDP_default +AFX_HIDP_FAILED_TO_START_PRINT = AFX_HIDP_default +AFX_HIDP_FAILED_TO_LAUNCH_HELP = AFX_HIDP_default +AFX_HIDP_INTERNAL_FAILURE = AFX_HIDP_default +AFX_HIDP_COMMAND_FAILURE = AFX_HIDP_default +AFX_HIDP_PARSE_INT = AFX_HIDP_default +AFX_HIDP_PARSE_REAL = AFX_HIDP_default +AFX_HIDP_PARSE_INT_RANGE = AFX_HIDP_default +AFX_HIDP_PARSE_REAL_RANGE = AFX_HIDP_default +AFX_HIDP_PARSE_STRING_SIZE = AFX_HIDP_default +AFX_HIDP_FAILED_INVALID_FORMAT = AFX_HIDP_default +AFX_HIDP_FAILED_INVALID_PATH = AFX_HIDP_default +AFX_HIDP_FAILED_DISK_FULL = AFX_HIDP_default +AFX_HIDP_FAILED_ACCESS_READ = AFX_HIDP_default +AFX_HIDP_FAILED_ACCESS_WRITE = AFX_HIDP_default +AFX_HIDP_FAILED_IO_ERROR_READ = AFX_HIDP_default +AFX_HIDP_FAILED_IO_ERROR_WRITE = AFX_HIDP_default +AFX_HIDP_STATIC_OBJECT = AFX_HIDP_default +AFX_HIDP_FAILED_TO_CONNECT = AFX_HIDP_default +AFX_HIDP_SERVER_BUSY = AFX_HIDP_default +AFX_HIDP_BAD_VERB = AFX_HIDP_default +AFX_HIDP_FAILED_MEMORY_ALLOC = AFX_HIDP_default +AFX_HIDP_FAILED_TO_NOTIFY = AFX_HIDP_default +AFX_HIDP_FAILED_TO_LAUNCH = AFX_HIDP_default +AFX_HIDP_ASK_TO_UPDATE = AFX_HIDP_default +AFX_HIDP_FAILED_TO_UPDATE = AFX_HIDP_default +AFX_HIDP_FAILED_TO_REGISTER = AFX_HIDP_default +AFX_HIDP_FAILED_TO_AUTO_REGISTER = AFX_HIDP_default + +[MAP] +#include D3Launch.hm + +[WINDOWS] +main="",(653,102,360,600),60672,(r14876671),(r12632256),f3 diff --git a/D3Launch/ia3dapi.h b/D3Launch/ia3dapi.h new file mode 100644 index 00000000..11aeaca3 --- /dev/null +++ b/D3Launch/ia3dapi.h @@ -0,0 +1,1313 @@ +/*--------------------------------------------------------------------------- + * + * A3D COM Interface Header File. + * + *--------------------------------------------------------------------------- + */ + +#ifndef _IA3DAPI_H_ +#define _IA3DAPI_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// A3D 1.0 Class ID {D8F1EEE0-F634-11cf-8700-00A0245D918B} +DEFINE_GUID(CLSID_A3d, 0xd8f1eee0, 0xf634, 0x11cf, 0x87, 0x0, 0x0, 0xa0, 0x24, 0x5d, 0x91, 0x8b); + +// A3D 2.0 Class ID {92FA2C24-253C-11d2-90FB-006008A1F441} +DEFINE_GUID(CLSID_A3dApi, 0x92fa2c24, 0x253c, 0x11d2, 0x90, 0xfb, 0x0, 0x60, 0x8, 0xa1, 0xf4, 0x41); + +//=================================================================== +// A3D 2.0 Interfaces +//=================================================================== + +// Forward declaration of COM interfaces +#ifdef __cplusplus +// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined +struct IA3d3; +struct IA3dGeom; +struct IA3dSource; +struct IA3dListener; +struct IA3dList; +struct IA3dMaterial; +struct IA3dEnvironment; +#endif // __cplusplus + +typedef struct IA3d3 *LPA3D3; +typedef struct IA3d4 *LPA3D4; +typedef struct IA3dGeom *LPA3DGEOM; +typedef struct IA3dSource *LPA3DSOURCE; +typedef struct IA3dListener *LPA3DLISTENER; +typedef struct IA3dList *LPA3DLIST; +typedef struct IA3dMaterial *LPA3DMATERIAL; +typedef struct IA3dEnvironment *LPA3DENVIRONMENT; + + +//=================================================================== +// Defined values +//=================================================================== + +// Feature flags +#define A3D_1ST_REFLECTIONS 0x00000002 +#define A3D_DIRECT_PATH_A3D 0x00000008 +#define A3D_DIRECT_PATH_GENERIC 0x00000020 +#define A3D_OCCLUSIONS 0x00000040 +#define A3D_DISABLE_SPLASHSCREEN 0x00000080 + +// Rendering modes +#define A3D_FASTEST 0x00000001 +#define A3D_QUICK 0x00000002 +#define A3D_NICEST 0x00000004 + +// Primitive input modes +#define A3D_INVALID_INPUTMODE -1 + +#define A3D_LINES 0x00000002 +#define A3D_TRIANGLES 0x00000003 +#define A3D_QUADS 0x00000004 +#define A3D_MATERIAL 0x00000005 + +#define A3D_SUBFACE 0x80000000 +#define A3D_VERTEX_MASK 0x0000000F + +#define A3D_SUB_LINES (A3D_LINES | A3D_SUBFACE) +#define A3D_SUB_TRIANGLES (A3D_TRIANGLES | A3D_SUBFACE) +#define A3D_SUB_QUADS (A3D_QUADS | A3D_SUBFACE) + +// Wall flags +#define A3D_SHELL_WALL 0x00000001 +#define A3D_TRANSPARENT_WALL 0x00000002 + +// Data types +typedef float A3DVAL, *LPA3DVAL; + +typedef A3DVAL A3DVECTOR[4]; +typedef A3DVAL A3DVERTEX[4]; + +/* + * NOTE: A3D matrices are column major. Indices are like this: + * + * | 0 4 8 12 | + * | 1 5 9 13 | + * | 2 6 10 14 | + * | 3 7 11 15 | + * + * Indexing is (column*4)+row. + * +*/ +typedef A3DVAL A3DMATRIX[16]; + +#define A3D_TRUE 1 +#define A3D_FALSE 0 + +// Epsilon good as zero gets +#define A3D_EPSILON (1.0e-6f) +#define A3D_EPSILON_SQUARED (1.0e-12f) + +#define A3D_DEFAULT 0 + +// Play options +#define A3D_SINGLE 0 +#define A3D_LOOPED 1 + +// Scene Types +#define A3D_SCENE_2D 2 +#define A3D_SCENE_3D 3 + +#define A3DSTATUS_PLAYING 0x00000001 +#define A3DSTATUS_BUFFERLOST 0x00000002 +#define A3DSTATUS_LOOPING 0x00000004 +#define A3DSTATUS_WAITING_FOR_FLUSH 0x00001000 + +// Coordinate system +#define A3D_RIGHT_HANDED_CS 0x00000000 +#define A3D_LEFT_HANDED_CS 0x00000001 + +// Cooperative Level +#define A3D_CL_NORMAL 0x00000001 +#define A3D_CL_EXCLUSIVE 0x00000003 + +// MaxMinDistance flags +#define A3D_AUDIBLE 0x00000000 +#define A3D_MUTE 0x00000001 + +#define A3DRENDERPREFS_A3D 0x00000000 +#define A3DRENDERPREFS_DEFAULT A3DRENDERPREFS_A3D + +#define A3DSOURCE_TRANSFORMMODE_NORMAL 0x00000000 +#define A3DSOURCE_TRANSFORMMODE_HEADRELATIVE 0x00000001 + +#define A3DSOURCE_RENDERMODE_A3D 0x00000000 +#define A3DSOURCE_RENDERMODE_MONO 0x00000001 +#define A3DSOURCE_RENDERMODE_1ST_REFLECTIONS 0x00000004 +#define A3DSOURCE_RENDERMODE_OCCLUSIONS 0x00000008 +#define A3DSOURCE_RENDERMODE_NATIVE 0x00000020 +#define A3DSOURCE_RENDERMODE_DEFAULT (A3DSOURCE_RENDERMODE_A3D | \ + A3DSOURCE_RENDERMODE_1ST_REFLECTIONS | \ + A3DSOURCE_RENDERMODE_OCCLUSIONS) + +// Notification +#define A3DSOURCE_WAVEEVENT_STOP 0xFFFFFFFF + +// Polygon render mode +#define A3DPOLY_RENDERMODE_1ST_REFLECTIONS 0x00000002 +#define A3DPOLY_RENDERMODE_OCCLUSIONS 0x00000040 + +#define A3DSOURCE_INITIAL_RENDERMODE_A3D 0x00000000 +#define A3DSOURCE_INITIAL_RENDERMODE_NATIVE 0x00000001 +#define A3DSOURCE_TYPEUNMANAGED 0x00000002 +#define A3DSOURCE_TYPESTREAMED 0x00000004 +#define A3DSOURCE_TYPEDEFAULT A3DSOURCE_INITIAL_RENDERMODE_A3D + +// Values for bOutputMode +#define OUTPUT_MODE_STEREO 0x00000001 +#define OUTPUT_MODE_QUAD 0x00000002 + +// Values for FrontXtalkMode and bRearXtalkMode +#define OUTPUT_HEADPHONES 0x00000001 +#define OUTPUT_SPEAKERS_WIDE 0x00000002 +#define OUTPUT_SPEAKERS_NARROW 0x00000003 + +// Values for Resource Management Mode +#define A3D_RESOURCE_MODE_OFF 0x00000000 +#define A3D_RESOURCE_MODE_NOTIFY 0x00000001 +#define A3D_RESOURCE_MODE_DYNAMIC 0x00000002 +#define A3D_RESOURCE_MODE_DYNAMIC_LOOPERS 0x00000003 +#define A3D_RESOURCE_MODE_LAST A3D_RESOURCE_MODE_DYNAMIC_LOOPERS + +// A3d Source Lock modes +#define A3D_FROMWRITECURSOR 0x00000001 +#define A3D_ENTIREBUFFER 0x00000002 + +// Version Definitions for A3DCAPS +#define A3D_CURRENT_VERSION IA3DVERSION_RELEASE20 + +#define IA3DVERSION_RELEASE10 10 +#define IA3DVERSION_RELEASE12 12 +#define IA3DVERSION_RELEASE20 20 + +// A3d Caps structure for A3d2 interface +// If Fail to get IA3d2 interface, version of DLL is IA3DVERSION_PRE12 + +typedef struct __A3DCAPS_SOFTWARE +{ + DWORD dwSize; // Use for internal version control + DWORD dwVersion; // For Backwards capablities purposes + DWORD dwFlags; + DWORD dwReserved; + DWORD dwReserved2; + DWORD dwOutputChannels; + DWORD dwMinSampleRate; + DWORD dwMaxSampleRate; + DWORD dwMax2DBuffers; + DWORD dwMax3DBuffers; +} A3DCAPS_SOFTWARE, *LPA3DCAPS_SOFTWARE; + +typedef struct __A3DCAPS_HARDWARE +{ + DWORD dwSize; // Use for internal version control + DWORD dwFlags; + DWORD dwReserved; + DWORD dwReserved2; + DWORD dwOutputChannels; + DWORD dwMinSampleRate; + DWORD dwMaxSampleRate; + DWORD dwMax2DBuffers; + DWORD dwMax3DBuffers; +} A3DCAPS_HARDWARE, *LPA3DCAPS_HARDWARE; + + +//=================================================================== +// IA3d +// +// The original IA3d interface. +//=================================================================== + +// {D8F1EEE1-F634-11cf-8700-00A0245D918B} +DEFINE_GUID(IID_IA3d, 0xd8f1eee1, 0xf634, 0x11cf, 0x87, 0x0, 0x0, 0xa0, 0x24, 0x5d, 0x91, 0x8b); + +#undef INTERFACE +#define INTERFACE IA3d + +typedef struct IA3d *LPIA3D; + +DECLARE_INTERFACE_(IA3d, IUnknown) +{ + // IUnknown Methods. + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID FAR *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IA3d Methods. + STDMETHOD(SetOutputMode) (THIS_ DWORD, DWORD, DWORD) PURE; + STDMETHOD(GetOutputMode) (THIS_ LPDWORD, LPDWORD, LPDWORD) PURE; + STDMETHOD(SetResourceManagerMode) (THIS_ DWORD) PURE; + STDMETHOD(GetResourceManagerMode) (THIS_ LPDWORD) PURE; + STDMETHOD(SetHFAbsorbFactor) (THIS_ FLOAT) PURE; + STDMETHOD(GetHFAbsorbFactor) (THIS_ FLOAT *) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IA3d_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IA3d_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IA3d_Release(p) (p)->lpVtbl->Release(p) +#define IA3d_SetOutputMode(p,a,b,c) (p)->lpVtbl->SetOutputMode(p,a,b,c) +#define IA3d_GetOutputMode(p,a,b,c) (p)->lpVtbl->GetOutputMode(p,a,b,c) +#define IA3d_SetResourceManagerMode(p,a) (p)->lpVtbl->SetResourceManagerMode(p,a) +#define IA3d_GetResourceManagerMode(p,a) (p)->lpVtbl->GetResourceManagerMode(p,a) +#define IA3d_SetHFAbsorbFactor(p,a) (p)->lpVtbl->SetHFAbsorbFactor(p,a) +#define IA3d_GetHFAbsorbFactor(p,a) (p)->lpVtbl->GetHFAbsorbFactor(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IA3d_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IA3d_AddRef(p) (p)->AddRef() +#define IA3d_Release(p) (p)->Release() +#define IA3d_SetOutputMode(p,a,b,c) (p)->SetOutputMode(a,b,c) +#define IA3d_GetOutputMode(p,a,b,c) (p)->GetOutputMode(a,b,c) +#define IA3d_SetResourceManagerMode(p,a) (p)->SetResourceManagerMode(a) +#define IA3d_GetResourceManagerMode(p,a) (p)->GetResourceManagerMode(a) +#define IA3d_SetHFAbsorbFactor(p,a) (p)->SetHFAbsorbFactor(a) +#define IA3d_GetHFAbsorbFactor(p,a) (p)->GetHFAbsorbFactor(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + + +//=================================================================== +// IA3d2 +// +// IA3d2 Interface definition. +//=================================================================== + +// {fb80d1e0-98d3-11d1-90fb-006008a1f441} +DEFINE_GUID(IID_IA3d2, 0xfb80d1e0, 0x98d3, 0x11d1, 0x90, 0xfb, 0x00, 0x60, 0x08, 0xa1, 0xf4, 0x41); + +#undef INTERFACE +#define INTERFACE IA3d2 + +typedef struct IA3d2 *LPIA3D2; + +DECLARE_INTERFACE_(IA3d2, IUnknown) +{ + // IUnknown Methods. + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID FAR *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IA3d Methods. + STDMETHOD(SetOutputMode) (THIS_ DWORD, DWORD, DWORD) PURE; + STDMETHOD(GetOutputMode) (THIS_ LPDWORD, LPDWORD, LPDWORD) PURE; + STDMETHOD(SetResourceManagerMode) (THIS_ DWORD) PURE; + STDMETHOD(GetResourceManagerMode) (THIS_ LPDWORD) PURE; + STDMETHOD(SetHFAbsorbFactor) (THIS_ FLOAT) PURE; + STDMETHOD(GetHFAbsorbFactor) (THIS_ FLOAT *) PURE; + + // IA3d2 Methods. + STDMETHOD(RegisterVersion) (THIS_ DWORD) PURE; + STDMETHOD(GetSoftwareCaps) (THIS_ LPA3DCAPS_SOFTWARE) PURE; + STDMETHOD(GetHardwareCaps) (THIS_ LPA3DCAPS_HARDWARE) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IA3d2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IA3d2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IA3d2_Release(p) (p)->lpVtbl->Release(p) +#define IA3d2_SetOutputMode(p,a,b,c) (p)->lpVtbl->SetOutputMode(p,a,b,c) +#define IA3d2_GetOutputMode(p,a,b,c) (p)->lpVtbl->GetOutputMode(p,a,b,c) +#define IA3d2_SetResourceManagerMode(p,a) (p)->lpVtbl->SetResourceManagerMode(p,a) +#define IA3d2_GetResourceManagerMode(p,a) (p)->lpVtbl->GetResourceManagerMode(p,a) +#define IA3d2_SetHFAbsorbFactor(p,a) (p)->lpVtbl->SetHFAbsorbFactor(p,a) +#define IA3d2_GetHFAbsorbFactor(p,a) (p)->lpVtbl->GetHFAbsorbFactor(p,a) +#define IA3d2_RegisterVersion(p,a) (p)->lpVtbl->RegisterVersion(p,a) +#define IA3d2_GetSoftwareCaps(p,a) (p)->lpVtbl->GetSoftwareCaps(p,a) +#define IA3d2_GetHardwareCaps(p,a) (p)->lpVtbl->GetHardwareCaps(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IA3d2_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IA3d2_AddRef(p) (p)->AddRef() +#define IA3d2_Release(p) (p)->Release() +#define IA3d2_SetOutputMode(p,a,b,c) (p)->SetOutputMode(a,b,c) +#define IA3d2_GetOutputMode(p,a,b,c) (p)->GetOutputMode(a,b,c) +#define IA3d2_SetResourceManagerMode(p,a) (p)->SetResourceManagerMode(a) +#define IA3d2_GetResourceManagerMode(p,a) (p)->GetResourceManagerMode(a) +#define IA3d2_SetHFAbsorbFactor(p,a) (p)->SetHFAbsorbFactor(a) +#define IA3d2_GetHFAbsorbFactor(p,a) (p)->GetHFAbsorbFactor(a) +#define IA3d2_RegisterVersion(p,a) (p)->RegisterVersion(a) +#define IA3d2_GetSoftwareCaps(p,a) (p)->GetSoftwareCaps(a) +#define IA3d2_GetHardwareCaps(p,a) (p)->GetHardwareCaps(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + +//=================================================================== +// IA3d3 +// +// The root object in A3D. +//=================================================================== + +// {C398E560-D90B-11d1-90FB-006008A1F441} +DEFINE_GUID(IID_IA3d3, 0xc398e560, 0xd90b, 0x11d1, 0x90, 0xfb, 0x0, 0x60, 0x8, 0xa1, 0xf4, 0x41); + +#undef INTERFACE +#define INTERFACE IA3d3 + +typedef struct IA3d3 *LPIA3D3; + +DECLARE_INTERFACE_(IA3d3, IUnknown) +{ + // IUnknown Methods. + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID FAR *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IA3d Methods. + STDMETHOD(SetOutputMode) (THIS_ DWORD, DWORD, DWORD) PURE; + STDMETHOD(GetOutputMode) (THIS_ LPDWORD, LPDWORD, LPDWORD) PURE; + STDMETHOD(SetResourceManagerMode) (THIS_ DWORD) PURE; + STDMETHOD(GetResourceManagerMode) (THIS_ LPDWORD) PURE; + STDMETHOD(SetHFAbsorbFactor) (THIS_ FLOAT) PURE; + STDMETHOD(GetHFAbsorbFactor) (THIS_ FLOAT *) PURE; + + // IA3d2 Methods. + STDMETHOD(RegisterVersion) (THIS_ DWORD) PURE; + STDMETHOD(GetSoftwareCaps) (THIS_ LPA3DCAPS_SOFTWARE) PURE; + STDMETHOD(GetHardwareCaps) (THIS_ LPA3DCAPS_HARDWARE) PURE; + + // IA3d3 Methods. + STDMETHOD(Clear) (THIS) PURE; + STDMETHOD(Flush) (THIS) PURE; + STDMETHOD(Compat) (THIS_ DWORD, DWORD) PURE; + STDMETHOD(Init) (THIS_ LPGUID, DWORD, DWORD) PURE; + STDMETHOD(IsFeatureAvailable) (THIS_ DWORD) PURE; + STDMETHOD(NewSource) (THIS_ DWORD, LPA3DSOURCE *) PURE; + STDMETHOD(DuplicateSource) (THIS_ LPA3DSOURCE, LPA3DSOURCE *) PURE; + STDMETHOD(SetCooperativeLevel) (THIS_ HWND, DWORD) PURE; + STDMETHOD(GetCooperativeLevel) (THIS_ LPDWORD) PURE; + STDMETHOD(SetMaxReflectionDelayTime) (THIS_ A3DVAL) PURE; + STDMETHOD(GetMaxReflectionDelayTime) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetCoordinateSystem) (THIS_ DWORD) PURE; + STDMETHOD(GetCoordinateSystem) (THIS_ LPDWORD) PURE; + STDMETHOD(SetOutputGain) (THIS_ A3DVAL) PURE; + STDMETHOD(GetOutputGain) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetNumFallbackSources) (THIS_ DWORD) PURE; + STDMETHOD(GetNumFallbackSources) (THIS_ LPDWORD) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IA3d3_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IA3d3_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IA3d3_Release(p) (p)->lpVtbl->Release(p) +#define IA3d3_SetOutputMode(p,a,b,c) (p)->lpVtbl->SetOutputMode(p,a,b,c) +#define IA3d3_GetOutputMode(p,a,b,c) (p)->lpVtbl->GetOutputMode(p,a,b,c) +#define IA3d3_SetResourceManagerMode(p,a) (p)->lpVtbl->SetResourceManagerMode(p,a) +#define IA3d3_GetResourceManagerMode(p,a) (p)->lpVtbl->GetResourceManagerMode(p,a) +#define IA3d3_SetHFAbsorbFactor(p,a) (p)->lpVtbl->SetHFAbsorbFactor(p,a) +#define IA3d3_GetHFAbsorbFactor(p,a) (p)->lpVtbl->GetHFAbsorbFactor(p,a) +#define IA3d3_RegisterVersion(p,a) (p)->lpVtbl->RegisterVersion(p,a) +#define IA3d3_GetSoftwareCaps(p,a) (p)->lpVtbl->GetSoftwareCaps(p,a) +#define IA3d3_GetHardwareCaps(p,a) (p)->lpVtbl->GetHardwareCaps(p,a) +#define IA3d3_Clear(p) (p)->lpVtbl->Clear(p) +#define IA3d3_Flush(p) (p)->lpVtbl->Flush(p) +#define IA3d3_Compat(p,a,b) (p)->lpVtbl->Compat(p,a,b) +#define IA3d3_Init(p,a,b,c) (p)->lpVtbl->Init(p,a,b,c) +#define IA3d3_IsFeatureAvailable(p,a) (p)->lpVtbl->IsFeatureAvailable(p,a) +#define IA3d3_NewSource(p,a,b) (p)->lpVtbl->NewSource(p,a,b) +#define IA3d3_DuplicateSource(p,a,b) (p)->lpVtbl->DuplicateSource(p,a,b) +#define IA3d3_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IA3d3_GetCooperativeLevel(p,a) (p)->lpVtbl->GetCooperativeLevel(p,a) +#define IA3d3_SetMaxReflectionDelayTime(p,a) (p)->lpVtbl->SetMaxReflectionDelayTime(p,a) +#define IA3d3_GetMaxReflectionDelayTime(p,a) (p)->lpVtbl->GetMaxReflectionDelayTime(p,a) +#define IA3d3_SetCoordinateSystem(p,a) (p)->lpVtbl->SetCoordinateSystem(p,a) +#define IA3d3_GetCoordinateSystem(p,a) (p)->lpVtbl->GetCoordinateSystem(p,a) +#define IA3d3_SetOutputGain(p,a) (p)->lpVtbl->SetOutputGain(p,a) +#define IA3d3_GetOutputGain(p,a) (p)->lpVtbl->GetOutputGain(p,a) +#define IA3d3_SetNumFallbackSources(p,a) (p)->lpVtbl->SetNumFallbackSources(p,a) +#define IA3d3_GetNumFallbackSources(p,a) (p)->lpVtbl->GetNumFallbackSources(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IA3d3_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IA3d3_AddRef(p) (p)->AddRef() +#define IA3d3_Release(p) (p)->Release() +#define IA3d3_SetOutputMode(p,a,b,c) (p)->SetOutputMode(a,b,c) +#define IA3d3_GetOutputMode(p,a,b,c) (p)->GetOutputMode(a,b,c) +#define IA3d3_SetResourceManagerMode(p,a) (p)->SetResourceManagerMode(a) +#define IA3d3_GetResourceManagerMode(p,a) (p)->GetResourceManagerMode(a) +#define IA3d3_SetHFAbsorbFactor(p,a) (p)->SetHFAbsorbFactor(a) +#define IA3d3_GetHFAbsorbFactor(p,a) (p)->GetHFAbsorbFactor(a) +#define IA3d3_RegisterVersion(p,a) (p)->RegisterVersion(a) +#define IA3d3_GetSoftwareCaps(p,a) (p)->GetSoftwareCaps(a) +#define IA3d3_GetHardwareCaps(p,a) (p)->GetHardwareCaps(a) +#define IA3d3_Clear(p) (p)->Clear() +#define IA3d3_Flush(p) (p)->Flush() +#define IA3d3_Compat(p,a,b) (p)->Compat(a,b) +#define IA3d3_Init(p,a,b,c) (p)->Init(a,b,c) +#define IA3d3_IsFeatureAvailable(p,a) (p)->IsFeatureAvailable(a) +#define IA3d3_NewSource(p,a,b) (p)->NewSource(a,b) +#define IA3d3_DuplicateSource(p,a,b) (p)->DuplicateSource(a,b) +#define IA3d3_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IA3d3_GetCooperativeLevel(p,a) (p)->GetCooperativeLevel(a) +#define IA3d3_SetMaxReflectionDelayTime(p,a) (p)->SetMaxReflectionDelayTime(a) +#define IA3d3_GetMaxReflectionDelayTime(p,a) (p)->GetMaxReflectionDelayTime(a) +#define IA3d3_SetCoordinateSystem(p,a) (p)->SetCoordinateSystem(a) +#define IA3d3_GetCoordinateSystem(p,a) (p)->GetCoordinateSystem(a) +#define IA3d3_SetOutputGain(p,a) (p)->SetOutputGain(a) +#define IA3d3_GetOutputGain(p,a) (p)->GetOutputGain(a) +#define IA3d3_SetNumFallbackSources(p,a) (p)->SetNumFallbackSources(a) +#define IA3d3_GetNumFallbackSources(p,a) (p)->GetNumFallbackSources(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + + +//=================================================================== +// IA3d4 +// +// The root object in A3D. +//=================================================================== + +// {E4C40280-CCBA-11d2-9DCF-00500411582F} +DEFINE_GUID(IID_IA3d4, 0xe4c40280, 0xccba, 0x11d2, 0x9d, 0xcf, 0x0, 0x50, 0x4, 0x11, 0x58, 0x2f); + +#undef INTERFACE +#define INTERFACE IA3d4 + +DECLARE_INTERFACE_(IA3d4, IUnknown) +{ + // IUnknown Methods. + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID FAR *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IA3d Methods. + STDMETHOD(SetOutputMode) (THIS_ DWORD, DWORD, DWORD) PURE; + STDMETHOD(GetOutputMode) (THIS_ LPDWORD, LPDWORD, LPDWORD) PURE; + STDMETHOD(SetResourceManagerMode) (THIS_ DWORD) PURE; + STDMETHOD(GetResourceManagerMode) (THIS_ LPDWORD) PURE; + STDMETHOD(SetHFAbsorbFactor) (THIS_ FLOAT) PURE; + STDMETHOD(GetHFAbsorbFactor) (THIS_ FLOAT *) PURE; + + // IA3d2 Methods. + STDMETHOD(RegisterVersion) (THIS_ DWORD) PURE; + STDMETHOD(GetSoftwareCaps) (THIS_ LPA3DCAPS_SOFTWARE) PURE; + STDMETHOD(GetHardwareCaps) (THIS_ LPA3DCAPS_HARDWARE) PURE; + + // IA3d3 Methods. + STDMETHOD(Clear) (THIS) PURE; + STDMETHOD(Flush) (THIS) PURE; + STDMETHOD(Compat) (THIS_ DWORD, DWORD) PURE; + STDMETHOD(Init) (THIS_ LPGUID, DWORD, DWORD) PURE; + STDMETHOD(IsFeatureAvailable) (THIS_ DWORD) PURE; + STDMETHOD(NewSource) (THIS_ DWORD, LPA3DSOURCE *) PURE; + STDMETHOD(DuplicateSource) (THIS_ LPA3DSOURCE, LPA3DSOURCE *) PURE; + STDMETHOD(SetCooperativeLevel) (THIS_ HWND, DWORD) PURE; + STDMETHOD(GetCooperativeLevel) (THIS_ LPDWORD) PURE; + STDMETHOD(SetMaxReflectionDelayTime) (THIS_ A3DVAL) PURE; + STDMETHOD(GetMaxReflectionDelayTime) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetCoordinateSystem) (THIS_ DWORD) PURE; + STDMETHOD(GetCoordinateSystem) (THIS_ LPDWORD) PURE; + STDMETHOD(SetOutputGain) (THIS_ A3DVAL) PURE; + STDMETHOD(GetOutputGain) (THIS_ LPA3DVAL) PURE; + + // IA3d4 Methods + STDMETHOD(SetNumFallbackSources) (THIS_ DWORD) PURE; + STDMETHOD(GetNumFallbackSources) (THIS_ LPDWORD) PURE; + STDMETHOD(SetRMPriorityBias) (THIS_ A3DVAL) PURE; + STDMETHOD(GetRMPriorityBias) (THIS_ LPA3DVAL) PURE; + STDMETHOD(DisableViewer) (THIS) PURE; + STDMETHOD(SetUnitsPerMeter) (THIS_ A3DVAL) PURE; + STDMETHOD(GetUnitsPerMeter) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetDopplerScale) (THIS_ A3DVAL) PURE; + STDMETHOD(GetDopplerScale) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetDistanceModelScale) (THIS_ A3DVAL) PURE; + STDMETHOD(GetDistanceModelScale) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetEq) (THIS_ A3DVAL) PURE; + STDMETHOD(GetEq) (THIS_ LPA3DVAL) PURE; + STDMETHOD(Shutdown) (THIS) PURE; + STDMETHOD(RegisterApp) (THIS_ REFIID) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IA3d4_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IA3d4_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IA3d4_Release(p) (p)->lpVtbl->Release(p) +#define IA3d4_SetOutputMode(p,a,b,c) (p)->lpVtbl->SetOutputMode(p,a,b,c) +#define IA3d4_GetOutputMode(p,a,b,c) (p)->lpVtbl->GetOutputMode(p,a,b,c) +#define IA3d4_SetResourceManagerMode(p,a) (p)->lpVtbl->SetResourceManagerMode(p,a) +#define IA3d4_GetResourceManagerMode(p,a) (p)->lpVtbl->GetResourceManagerMode(p,a) +#define IA3d4_SetHFAbsorbFactor(p,a) (p)->lpVtbl->SetHFAbsorbFactor(p,a) +#define IA3d4_GetHFAbsorbFactor(p,a) (p)->lpVtbl->GetHFAbsorbFactor(p,a) +#define IA3d4_RegisterVersion(p,a) (p)->lpVtbl->RegisterVersion(p,a) +#define IA3d4_GetSoftwareCaps(p,a) (p)->lpVtbl->GetSoftwareCaps(p,a) +#define IA3d4_GetHardwareCaps(p,a) (p)->lpVtbl->GetHardwareCaps(p,a) +#define IA3d4_Clear(p) (p)->lpVtbl->Clear(p) +#define IA3d4_Flush(p) (p)->lpVtbl->Flush(p) +#define IA3d4_Compat(p,a,b) (p)->lpVtbl->Compat(p,a,b) +#define IA3d4_Init(p,a,b,c) (p)->lpVtbl->Init(p,a,b,c) +#define IA3d4_IsFeatureAvailable(p,a) (p)->lpVtbl->IsFeatureAvailable(p,a) +#define IA3d4_NewSource(p,a,b) (p)->lpVtbl->NewSource(p,a,b) +#define IA3d4_DuplicateSource(p,a,b) (p)->lpVtbl->DuplicateSource(p,a,b) +#define IA3d4_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IA3d4_GetCooperativeLevel(p,a) (p)->lpVtbl->GetCooperativeLevel(p,a) +#define IA3d4_SetMaxReflectionDelayTime(p,a) (p)->lpVtbl->SetMaxReflectionDelayTime(p,a) +#define IA3d4_GetMaxReflectionDelayTime(p,a) (p)->lpVtbl->GetMaxReflectionDelayTime(p,a) +#define IA3d4_SetCoordinateSystem(p,a) (p)->lpVtbl->SetCoordinateSystem(p,a) +#define IA3d4_GetCoordinateSystem(p,a) (p)->lpVtbl->GetCoordinateSystem(p,a) +#define IA3d4_SetOutputGain(p,a) (p)->lpVtbl->SetOutputGain(p,a) +#define IA3d4_GetOutputGain(p,a) (p)->lpVtbl->GetOutputGain(p,a) +#define IA3d4_SetNumFallbackSources(p,a) (p)->lpVtbl->SetNumFallbackSources(p,a) +#define IA3d4_GetNumFallbackSources(p,a) (p)->lpVtbl->GetNumFallbackSources(p,a) +#define IA3d4_SetRMPriorityBias(p,a) (p)->lpVtbl->SetRMPriorityBias(p,a) +#define IA3d4_GetRMPriorityBias(p,a) (p)->lpVtbl->GetRMPriorityBias(p,a) +#define IA3d4_DisableViewer(p) (p)->lpVtbl->DisableViewer(p) +#define IA3d4_SetUnitsPerMeter(p,a) (p)->lpVtbl->SetUnitsPerMeter(p,a) +#define IA3d4_GetUnitsPerMeter(p,a) (p)->lpVtbl->GetUnitsPerMeter(p,a) +#define IA3d4_SetDopplerScale(p,a) (p)->lpVtbl->SetDopplerScale(p,a) +#define IA3d4_GetDopplerScale(p,a) (p)->lpVtbl->GetDopplerScale(p,a) +#define IA3d4_SetDistanceModelScale(p,a) (p)->lpVtbl->SetDistanceModelScale(p,a) +#define IA3d4_GetDistanceModelScale(p,a) (p)->lpVtbl->GetDistanceModelScale(p,a) +#define IA3d4_SetEq(p,a) (p)->lpVtbl->SetEq(p,a) +#define IA3d4_GetEq(p,a) (p)->lpVtbl->GetEq(p,a) +#define IA3d4_Shutdown(p) (p)->lpVtbl->Shutdown(p) +#define IA3d4_RegisterApp(p,a) (p)->lpVtbl->RegisterApp(p,a) + +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IA3d4_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IA3d4_AddRef(p) (p)->AddRef() +#define IA3d4_Release(p) (p)->Release() +#define IA3d4_SetOutputMode(p,a,b,c) (p)->SetOutputMode(a,b,c) +#define IA3d4_GetOutputMode(p,a,b,c) (p)->GetOutputMode(a,b,c) +#define IA3d4_SetResourceManagerMode(p,a) (p)->SetResourceManagerMode(a) +#define IA3d4_GetResourceManagerMode(p,a) (p)->GetResourceManagerMode(a) +#define IA3d4_SetHFAbsorbFactor(p,a) (p)->SetHFAbsorbFactor(a) +#define IA3d4_GetHFAbsorbFactor(p,a) (p)->GetHFAbsorbFactor(a) +#define IA3d4_RegisterVersion(p,a) (p)->RegisterVersion(a) +#define IA3d4_GetSoftwareCaps(p,a) (p)->GetSoftwareCaps(a) +#define IA3d4_GetHardwareCaps(p,a) (p)->GetHardwareCaps(a) +#define IA3d4_Clear(p) (p)->Clear() +#define IA3d4_Flush(p) (p)->Flush() +#define IA3d4_Compat(p,a,b) (p)->Compat(a,b) +#define IA3d4_Init(p,a,b,c) (p)->Init(a,b,c) +#define IA3d4_IsFeatureAvailable(p,a) (p)->IsFeatureAvailable(a) +#define IA3d4_NewSource(p,a,b) (p)->NewSource(a,b) +#define IA3d4_DuplicateSource(p,a,b) (p)->DuplicateSource(a,b) +#define IA3d4_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IA3d4_GetCooperativeLevel(p,a) (p)->GetCooperativeLevel(a) +#define IA3d4_SetMaxReflectionDelayTime(p,a) (p)->SetMaxReflectionDelayTime(a) +#define IA3d4_GetMaxReflectionDelayTime(p,a) (p)->GetMaxReflectionDelayTime(a) +#define IA3d4_SetCoordinateSystem(p,a) (p)->SetCoordinateSystem(a) +#define IA3d4_GetCoordinateSystem(p,a) (p)->GetCoordinateSystem(a) +#define IA3d4_SetOutputGain(p,a) (p)->SetOutputGain(a) +#define IA3d4_GetOutputGain(p,a) (p)->GetOutputGain(a) +#define IA3d4_SetNumFallbackSources(p,a) (p)->SetNumFallbackSources(a) +#define IA3d4_GetNumFallbackSources(p,a) (p)->GetNumFallbackSources(a) +#define IA3d4_SetRMPriorityBias(p,a) (p)->SetRMPriorityBias(a) +#define IA3d4_GetRMPriorityBias(p,a) (p)->GetRMPriorityBias(a) +#define IA3d4_DisableViewer(p) (p)->DisableViewer() +#define IA3d4_SetUnitsPerMeter(p,a) (p)->SetUnitsPerMeter(a) +#define IA3d4_GetUnitsPerMeter(p,a) (p)->GetUnitsPerMeter(a) +#define IA3d4_SetDopplerScale(p,a) (p)->SetDopplerScale(a) +#define IA3d4_GetDopplerScale(p,a) (p)->GetDopplerScale(a) +#define IA3d4_SetDistanceModelScale(p,a) (p)->SetDistanceModelScale(a) +#define IA3d4_GetDistanceModelScale(p,a) (p)->GetDistanceModelScale(a) +#define IA3d4_SetEq(p,a) (p)->SetEq(a) +#define IA3d4_GetEq(p,a) (p)->GetEq(a) +#define IA3d4_Shutdown(p) (p)->Shutdown() +#define IA3d4_RegisterApp(p,a) (p)->RegisterApp(a) + +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + + +//=================================================================== +// IA3dGeom +// +// The low level geometry renderer. +//=================================================================== + +// {C398E561-D90B-11d1-90FB-006008A1F441} +DEFINE_GUID(IID_IA3dGeom, 0xc398e561, 0xd90b, 0x11d1, 0x90, 0xfb, 0x0, 0x60, 0x8, 0xa1, 0xf4, 0x41); + +#undef INTERFACE +#define INTERFACE IA3dGeom + +DECLARE_INTERFACE_(IA3dGeom, IUnknown) +{ + // IUnknown Methods. + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID FAR *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IA3dGeom Methods. + STDMETHOD(Enable) (THIS_ DWORD) PURE; + STDMETHOD(Disable) (THIS_ DWORD) PURE; + STDMETHOD_(BOOL, IsEnabled) (THIS_ DWORD) PURE; + STDMETHOD(SetOcclusionMode) (THIS_ DWORD) PURE; + STDMETHOD(GetOcclusionMode) (THIS_ LPDWORD) PURE; + STDMETHOD(SetReflectionMode) (THIS_ DWORD) PURE; + STDMETHOD(GetReflectionMode) (THIS_ LPDWORD) PURE; + STDMETHOD(SetReflectionGainScale) (THIS_ A3DVAL) PURE; + STDMETHOD(GetReflectionGainScale) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetReflectionDelayScale) (THIS_ A3DVAL) PURE; + STDMETHOD(GetReflectionDelayScale) (THIS_ LPA3DVAL) PURE; + STDMETHOD_(ULONG, PushMatrix) (THIS) PURE; + STDMETHOD_(ULONG, PopMatrix) (THIS) PURE; + STDMETHOD(LoadIdentity) (THIS) PURE; + STDMETHOD(LoadMatrix) (THIS_ A3DMATRIX) PURE; + STDMETHOD(GetMatrix) (THIS_ A3DMATRIX) PURE; + STDMETHOD(MultMatrix) (THIS_ A3DMATRIX) PURE; + STDMETHOD(Translate3f) (THIS_ A3DVAL, A3DVAL, A3DVAL) PURE; + STDMETHOD(Translate3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(Rotate3f) (THIS_ A3DVAL, A3DVAL, A3DVAL, A3DVAL) PURE; + STDMETHOD(Rotate3fv) (THIS_ A3DVAL, LPA3DVAL) PURE; + STDMETHOD(Scale3f) (THIS_ A3DVAL, A3DVAL, A3DVAL) PURE; + STDMETHOD(Scale3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(Begin) (THIS_ DWORD) PURE; + STDMETHOD(End) (THIS) PURE; + STDMETHOD(Vertex3f) (THIS_ A3DVAL, A3DVAL, A3DVAL) PURE; + STDMETHOD(Vertex3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(Normal3f) (THIS_ A3DVAL, A3DVAL, A3DVAL) PURE; + STDMETHOD(Normal3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(Tag) (THIS_ DWORD) PURE; + STDMETHOD(SetOpeningFactorf) (THIS_ A3DVAL ) PURE; + STDMETHOD(SetOpeningFactorfv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(NewMaterial) (THIS_ LPA3DMATERIAL *) PURE; + STDMETHOD(BindMaterial) (THIS_ LPA3DMATERIAL) PURE; + STDMETHOD(NewList) (THIS_ LPA3DLIST *) PURE; + STDMETHOD(BindListener) (THIS) PURE; + STDMETHOD(BindSource) (THIS_ LPA3DSOURCE) PURE; + STDMETHOD(NewEnvironment) (THIS_ LPA3DENVIRONMENT *) PURE; + STDMETHOD(BindEnvironment) (THIS_ LPA3DENVIRONMENT ) PURE; + STDMETHOD(SetRenderMode) (THIS_ DWORD) PURE; + STDMETHOD(GetRenderMode) (THIS_ LPDWORD) PURE; + STDMETHOD(SetPolygonBloatFactor) (THIS_ A3DVAL) PURE; + STDMETHOD(GetPolygonBloatFactor) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetReflectionUpdateInterval) (THIS_ DWORD) PURE; + STDMETHOD(GetReflectionUpdateInterval) (THIS_ LPDWORD) PURE; + STDMETHOD(SetOcclusionUpdateInterval) (THIS_ DWORD) PURE; + STDMETHOD(GetOcclusionUpdateInterval) (THIS_ LPDWORD) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IA3dGeom_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IA3dGeom_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IA3dGeom_Release(p) (p)->lpVtbl->Release(p) +#define IA3dGeom_Enable(p,a) (p)->lpVtbl->Enable(p,a) +#define IA3dGeom_Disable(p,a) (p)->lpVtbl->Disable(p,a) +#define IA3dGeom_IsEnabled(p,a) (p)->lpVtbl->IsEnabled(p,a) +#define IA3dGeom_SetOcclusionMode(p,a) (p)->lpVtbl->SetOcclusionMode(p,a) +#define IA3dGeom_GetOcclusionMode(p,a) (p)->lpVtbl->GetOcclusionMode(p,a) +#define IA3dGeom_SetReflectionMode(p,a) (p)->lpVtbl->SetReflectionMode(p,a) +#define IA3dGeom_GetReflectionMode(p,a) (p)->lpVtbl->GetReflectionMode(p,a) +#define IA3dGeom_SetReflectionGainScale(p,a) (p)->lpVtbl->SetReflectionGainScale(p,a) +#define IA3dGeom_GetReflectionGainScale(p,a) (p)->lpVtbl->GetReflectionGainScale(p,a) +#define IA3dGeom_SetReflectionDelayScale(p,a) (p)->lpVtbl->SetReflectionDelayScale(p,a) +#define IA3dGeom_GetReflectionDelayScale(p,a) (p)->lpVtbl->GetReflectionDelayScale(p,a) +#define IA3dGeom_PushMatrix(p) (p)->lpVtbl->PushMatrix(p) +#define IA3dGeom_PopMatrix(p) (p)->lpVtbl->PopMatrix(p) +#define IA3dGeom_LoadIdentity(p) (p)->lpVtbl->LoadIdentity(p) +#define IA3dGeom_LoadMatrix(p,a) (p)->lpVtbl->LoadMatrix(p,a) +#define IA3dGeom_GetMatrix(p,a) (p)->lpVtbl->GetMatrix(p,a) +#define IA3dGeom_MultMatrix(p,a) (p)->lpVtbl->MultMatrix(p,a) +#define IA3dGeom_Translate3f(p,a,b,c) (p)->lpVtbl->Translate3f(p,a,b,c) +#define IA3dGeom_Translate3fv(p,a) (p)->lpVtbl->Translate3fv(p,a) +#define IA3dGeom_Rotate3f(p,a,b,c,d) (p)->lpVtbl->Rotate3f(p,a,b,c,d) +#define IA3dGeom_Rotate3fv(p,a,b) (p)->lpVtbl->Rotate3fv(p,a,b) +#define IA3dGeom_Scale3f(p,a,b,c) (p)->lpVtbl->Scale3f(p,a,b,c) +#define IA3dGeom_Scale3fv(p,a) (p)->lpVtbl->Scale3fv(p,a) +#define IA3dGeom_Begin(p,a) (p)->lpVtbl->Begin(p,a) +#define IA3dGeom_End(p) (p)->lpVtbl->End(p) +#define IA3dGeom_Vertex3f(p,a,b,c) (p)->lpVtbl->Vertex3f(p,a,b,c) +#define IA3dGeom_Vertex3fv(p,a) (p)->lpVtbl->Vertex3fv(p,a) +#define IA3dGeom_Normal3f(p,a,b,c) (p)->lpVtbl->Normal3f(p,a,b,c) +#define IA3dGeom_Normal3fv(p,a) (p)->lpVtbl->Normal3fv(p,a) +#define IA3dGeom_Tag(p,a) (p)->lpVtbl->Tag(p,a) +#define IA3dGeom_SetOpeningFactorf(p,a) (p)->lpVtbl->SetOpeningFactorf(p,a) +#define IA3dGeom_SetOpeningFactorfv(p,a) (p)->lpVtbl->SetOpeningFactorfv(p,a) +#define IA3dGeom_NewMaterial(p,a) (p)->lpVtbl->NewMaterial(p,a) +#define IA3dGeom_BindMaterial(p,a) (p)->lpVtbl->BindMaterial(p,a) +#define IA3dGeom_NewList(p,a) (p)->lpVtbl->NewList(p,a) +#define IA3dGeom_BindListener(p) (p)->lpVtbl->BindListener(p) +#define IA3dGeom_BindSource(p,a) (p)->lpVtbl->BindSource(p,a) +#define IA3dGeom_NewEnvironment(p,a) (p)->lpVtbl->NewEnvironment(p,a) +#define IA3dGeom_BindEnvironment(p,a) (p)->lpVtbl->BindEnvironment(p,a) +#define IA3dGeom_SetRenderMode(p,a) (p)->lpVtbl->SetRenderMode(p,a) +#define IA3dGeom_GetRenderMode(p,a) (p)->lpVtbl->GetRenderMode(p,a) +#define IA3dGeom_SetPolygonBloatFactor(p,a) (p)->lpVtbl->SetPolygonBloatFactor(p,a) +#define IA3dGeom_GetPolygonBloatFactor(p,a) (p)->lpVtbl->GetPolygonBloatFactor(p,a) +#define IA3dGeom_SetReflectionUpdateInterval(p,a) (p)->lpVtbl->SetReflectionUpdateInterval(p,a) +#define IA3dGeom_GetReflectionUpdateInterval(p,a) (p)->lpVtbl->GetReflectionUpdateInterval(p,a) +#define IA3dGeom_SetOcclusionUpdateInterval(p,a) (p)->lpVtbl->SetOcclusionUpdateInterval(p,a) +#define IA3dGeom_GetOcclusionUpdateInterval(p,a) (p)->lpVtbl->GetOcclusionUpdateInterval(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IA3dGeom_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IA3dGeom_AddRef(p) (p)->AddRef() +#define IA3dGeom_Release(p) (p)->Release() +#define IA3dGeom_Enable(p,a) (p)->Enable(a) +#define IA3dGeom_Disable(p,a) (p)->Disable(a) +#define IA3dGeom_IsEnabled(p,a) (p)->IsEnabled(a) +#define IA3dGeom_SetOcclusionMode(p,a) (p)->SetOcclusionMode(a) +#define IA3dGeom_GetOcclusionMode(p,a) (p)->GetOcclusionMode(a) +#define IA3dGeom_SetReflectionMode(p,a) (p)->SetReflectionMode(a) +#define IA3dGeom_GetReflectionMode(p,a) (p)->GetReflectionMode(a) +#define IA3dGeom_SetReflectionGainScale(p,a) (p)->SetReflectionGainScale(a) +#define IA3dGeom_GetReflectionGainScale(p,a) (p)->GetReflectionGainScale(a) +#define IA3dGeom_SetReflectionDelayScale(p,a) (p)->SetReflectionDelayScale(a) +#define IA3dGeom_GetReflectionDelayScale(p,a) (p)->GetReflectionDelayScale(a) +#define IA3dGeom_PushMatrix(p) (p)->PushMatrix() +#define IA3dGeom_PopMatrix(p) (p)->PopMatrix() +#define IA3dGeom_LoadIdentity(p) (p)->LoadIdentity() +#define IA3dGeom_LoadMatrix(p,a) (p)->LoadMatrix(a) +#define IA3dGeom_GetMatrix(p,a) (p)->GetMatrix(a) +#define IA3dGeom_MultMatrix(p,a) (p)->MultMatrix(a) +#define IA3dGeom_Translate3f(p,a,b,c) (p)->Translate3f(a,b,c) +#define IA3dGeom_Translate3fv(p,a) (p)->Translate3fv(a) +#define IA3dGeom_Rotate3f(p,a,b,c,d) (p)->Rotate3f(a,b,c,d) +#define IA3dGeom_Rotate3fv(p,a,b) (p)->Rotate3fv(a,b) +#define IA3dGeom_Scale3f(p,a,b,c) (p)->Scale3f(a,b,c) +#define IA3dGeom_Scale3fv(p,a) (p)->Scale3fv(a) +#define IA3dGeom_Begin(p,a) (p)->Begin(a) +#define IA3dGeom_End(p) (p)->End() +#define IA3dGeom_Vertex3f(p,a,b,c) (p)->Vertex3f(a,b,c) +#define IA3dGeom_Vertex3fv(p,a) (p)->Vertex3fv(a) +#define IA3dGeom_Normal3f(p,a,b,c) (p)->Normal3f(a,b,c) +#define IA3dGeom_Normal3fv(p,a) (p)->Normal3fv(a) +#define IA3dGeom_Tag(p,a) (p)->Tag(a) +#define IA3dGeom_SetOpeningFactorf(p,a) (p)->SetOpeningFactorf(p,a) +#define IA3dGeom_SetOpeningFactorfv(p,a) (p)->SetOpeningFactorfv(p,a) +#define IA3dGeom_NewMaterial(p,a) (p)->NewMaterial(a) +#define IA3dGeom_BindMaterial(p,a) (p)->BindMaterial(a) +#define IA3dGeom_NewList(p,a) (p)->NewList(a) +#define IA3dGeom_BindListener(p) (p)->BindListener() +#define IA3dGeom_BindSource(p,a) (p)->BindSource(a) +#define IA3dGeom_NewEnvironment(p,a) (p)->NewEnvironment(a) +#define IA3dGeom_BindEnvironment(p,a) (p)->BindEnvironment(a) +#define IA3dGeom_SetRenderMode(p,a) (p)->SetRenderMode(a) +#define IA3dGeom_GetRenderMode(p,a) (p)->GetRenderMode(a) +#define IA3dGeom_SetPolygonBloatFactor(p,a) (p)->SetPolygonBloatFactor(a) +#define IA3dGeom_GetPolygonBloatFactor(p,a) (p)->GetPolygonBloatFactor(a) +#define IA3dGeom_SetReflectionUpdateInterval(p,a) (p)->SetReflectionUpdateInterval(a) +#define IA3dGeom_GetReflectionUpdateInterval(p,a) (p)->GetReflectionUpdateInterval(a) +#define IA3dGeom_SetOcclusionUpdateInterval(p,a) (p)->SetOcclusionUpdateInterval(a) +#define IA3dGeom_GetOcclusionUpdateInterval(p,a) (p)->GetOcclusionUpdateInterval(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + + +//=================================================================== +// IA3dSource +// +// A sound source. +//=================================================================== + +// {C398E562-D90B-11d1-90FB-006008A1F441} +DEFINE_GUID(IID_IA3dSource, 0xc398e562, 0xd90b, 0x11d1, 0x90, 0xfb, 0x0, 0x60, 0x8, 0xa1, 0xf4, 0x41); + +#undef INTERFACE +#define INTERFACE IA3dSource + +DECLARE_INTERFACE_(IA3dSource, IUnknown) +{ + // IUnknown Methods. + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID FAR *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IA3dSource Methods. + STDMETHOD(LoadWaveFile) (THIS_ LPSTR) PURE; + STDMETHOD(LoadWaveData) (THIS_ LPVOID, DWORD) PURE; + STDMETHOD(AllocateWaveData) (THIS_ INT) PURE; + STDMETHOD(FreeWaveData) (THIS) PURE; + STDMETHOD(SetWaveFormat) (THIS_ LPVOID) PURE; + STDMETHOD(GetWaveFormat) (THIS_ LPVOID) PURE; + STDMETHOD(GetWaveSize) (THIS) PURE; + STDMETHOD(GetType) (THIS_ LPDWORD) PURE; + STDMETHOD(Lock) (THIS_ DWORD, DWORD, LPVOID *, LPDWORD, LPVOID *, LPDWORD, DWORD) PURE; + STDMETHOD(Unlock) (THIS_ LPVOID, DWORD, LPVOID, DWORD) PURE; + STDMETHOD(Play) (THIS_ INT) PURE; + STDMETHOD(Stop) (THIS) PURE; + STDMETHOD(Rewind) (THIS) PURE; + STDMETHOD(SetWaveTime) (THIS_ A3DVAL) PURE; + STDMETHOD(GetWaveTime) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetWavePosition) (THIS_ DWORD) PURE; + STDMETHOD(GetWavePosition) (THIS_ LPDWORD) PURE; + STDMETHOD(SetPosition3f) (THIS_ A3DVAL, A3DVAL, A3DVAL) PURE; + STDMETHOD(GetPosition3f) (THIS_ LPA3DVAL, LPA3DVAL, LPA3DVAL) PURE; + STDMETHOD(SetPosition3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(GetPosition3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetOrientationAngles3f) (THIS_ A3DVAL, A3DVAL, A3DVAL) PURE; + STDMETHOD(GetOrientationAngles3f) (THIS_ LPA3DVAL, LPA3DVAL, LPA3DVAL) PURE; + STDMETHOD(SetOrientationAngles3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(GetOrientationAngles3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetOrientation6f) (THIS_ A3DVAL, A3DVAL, A3DVAL, A3DVAL, A3DVAL, A3DVAL) PURE; + STDMETHOD(GetOrientation6f) (THIS_ LPA3DVAL, LPA3DVAL, LPA3DVAL, LPA3DVAL, LPA3DVAL, LPA3DVAL) PURE; + STDMETHOD(SetOrientation6fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(GetOrientation6fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetVelocity3f) (THIS_ A3DVAL, A3DVAL, A3DVAL) PURE; + STDMETHOD(GetVelocity3f) (THIS_ LPA3DVAL, LPA3DVAL, LPA3DVAL) PURE; + STDMETHOD(SetVelocity3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(GetVelocity3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetCone) (THIS_ A3DVAL, A3DVAL, A3DVAL) PURE; + STDMETHOD(GetCone) (THIS_ LPA3DVAL, LPA3DVAL, LPA3DVAL) PURE; + STDMETHOD(SetMinMaxDistance) (THIS_ A3DVAL, A3DVAL, DWORD) PURE; + STDMETHOD(GetMinMaxDistance) (THIS_ LPA3DVAL, LPA3DVAL, LPDWORD) PURE; + STDMETHOD(SetGain) (THIS_ A3DVAL) PURE; + STDMETHOD(GetGain) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetPitch) (THIS_ A3DVAL) PURE; + STDMETHOD(GetPitch) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetDopplerScale) (THIS_ A3DVAL) PURE; + STDMETHOD(GetDopplerScale) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetDistanceModelScale) (THIS_ A3DVAL) PURE; + STDMETHOD(GetDistanceModelScale) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetEq) (THIS_ A3DVAL) PURE; + STDMETHOD(GetEq) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetPriority) (THIS_ A3DVAL) PURE; + STDMETHOD(GetPriority) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetRenderMode) (THIS_ DWORD) PURE; + STDMETHOD(GetRenderMode) (THIS_ LPDWORD) PURE; + STDMETHOD(GetAudibility) (THIS_ LPA3DVAL) PURE; + STDMETHOD(GetOcclusionFactor) (THIS_ LPA3DVAL) PURE; + STDMETHOD(GetStatus) (THIS_ LPDWORD) PURE; + STDMETHOD(SetPanValues) (THIS_ DWORD, LPA3DVAL) PURE; + STDMETHOD(GetPanValues) (THIS_ DWORD, LPA3DVAL) PURE; + STDMETHOD(SetWaveEvent) (THIS_ DWORD, HANDLE) PURE; + STDMETHOD(ClearWaveEvents) (THIS) PURE; + STDMETHOD(SetTransformMode) (THIS_ DWORD) PURE; + STDMETHOD(GetTransformMode) (THIS_ LPDWORD) PURE; + STDMETHOD(SetReflectionDelayScale) (THIS_ A3DVAL) PURE; + STDMETHOD(GetReflectionDelayScale) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetReflectionGainScale) (THIS_ A3DVAL) PURE; + STDMETHOD(GetReflectionGainScale) (THIS_ LPA3DVAL) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IA3dSource_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IA3dSource_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IA3dSource_Release(p) (p)->lpVtbl->Release(p) +#define IA3dSource_LoadWaveFile(p,a) (p)->lpVtbl->LoadWaveFile(p,a) +#define IA3dSource_LoadWaveData(p,a,b) (p)->lpVtbl->LoadWaveData(p,a,b) +#define IA3dSource_AllocateWaveData(p,a) (p)->lpVtbl->AllocateWaveData(p,a) +#define IA3dSource_FreeWaveData(p) (p)->lpVtbl->FreeWaveData(p) +#define IA3dSource_SetWaveFormat(p,a) (p)->lpVtbl->SetWaveFormat(p,a) +#define IA3dSource_GetWaveFormat(p,a) (p)->lpVtbl->GetWaveFormat(p,a) +#define IA3dSource_GetWaveSize(p) (p)->lpVtbl->GetWaveSize(p) +#define IA3dSource_GetType(p,a) (p)->lpVtbl->GetType(p,a) +#define IA3dSource_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g) +#define IA3dSource_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d) +#define IA3dSource_Play(p,a) (p)->lpVtbl->Play(p,a) +#define IA3dSource_Stop(p) (p)->lpVtbl->Stop(p) +#define IA3dSource_Rewind(p) (p)->lpVtbl->Rewind(p) +#define IA3dSource_SetWaveTime(p,a) (p)->lpVtbl->SetWaveTime(p,a) +#define IA3dSource_GetWaveTime(p,a) (p)->lpVtbl->GetWaveTime(p,a) +#define IA3dSource_SetWavePosition(p,a) (p)->lpVtbl->SetWavePosition(p,a) +#define IA3dSource_GetWavePosition(p,a) (p)->lpVtbl->GetWavePosition(p,a) +#define IA3dSource_SetPosition3f(p,a,b,c) (p)->lpVtbl->SetPosition3f(p,a,b,c) +#define IA3dSource_GetPosition3f(p,a,b,c) (p)->lpVtbl->GetPosition3f(p,a,b,c) +#define IA3dSource_SetPosition3fv(p,a) (p)->lpVtbl->SetPosition3fv(p,a) +#define IA3dSource_GetPosition3fv(p,a) (p)->lpVtbl->GetPosition3fv(p,a) +#define IA3dSource_SetOrientationAngles3f(p,a,b,c) (p)->lpVtbl->SetOrientationAngles3f(p,a,b,c) +#define IA3dSource_GetOrientationAngles3f(p,a,b,c) (p)->lpVtbl->GetOrientationAngles3f(p,a,b,c) +#define IA3dSource_SetOrientationAngles3fv(p,a) (p)->lpVtbl->SetOrientationAngles3fv(p,a) +#define IA3dSource_GetOrientationAngles3fv(p,a) (p)->lpVtbl->GetOrientationAngles3fv(p,a) +#define IA3dSource_SetOrientation6f(p,a,b,c,d,e,f) (p)->lpVtbl->SetOrientation6f(p,a,b,c,d,e,f) +#define IA3dSource_GetOrientation6f(p,a,b,c,d,e,f) (p)->lpVtbl->GetOrientation6f(p,a,b,c,d,e,f) +#define IA3dSource_SetOrientation6fv(p,a) (p)->lpVtbl->SetOrientation6fv(p,a) +#define IA3dSource_GetOrientation6fv(p,a) (p)->lpVtbl->GetOrientation6fv(p,a) +#define IA3dSource_SetVelocity3f(p,a,b,c) (p)->lpVtbl->SetVelocity3f(p,a,b,c) +#define IA3dSource_GetVelocity3f(p,a,b,c) (p)->lpVtbl->GetVelocity3f(p,a,b,c) +#define IA3dSource_SetVelocity3fv(p,a) (p)->lpVtbl->SetVelocity3fv(p,a) +#define IA3dSource_GetVelocity3fv(p,a) (p)->lpVtbl->GetVelocity3fv(p,a) +#define IA3dSource_SetCone(p,a,b,c) (p)->lpVtbl->SetCone(p,a,b,c) +#define IA3dSource_GetCone(p,a,b,c) (p)->lpVtbl->GetCone(p,a,b,c) +#define IA3dSource_SetMinMaxDistance(p,a,b,c) (p)->lpVtbl->SetMinMaxDistance(p,a,b,c) +#define IA3dSource_GetMinMaxDistance(p,a,b,c) (p)->lpVtbl->GetMinMaxDistance(p,a,b,c) +#define IA3dSource_SetGain(p,a) (p)->lpVtbl->SetGain(p,a) +#define IA3dSource_GetGain(p,a) (p)->lpVtbl->GetGain(p,a) +#define IA3dSource_SetPitch(p,a) (p)->lpVtbl->SetPitch(p,a) +#define IA3dSource_GetPitch(p,a) (p)->lpVtbl->GetPitch(p,a) +#define IA3dSource_SetDopplerScale(p,a) (p)->lpVtbl->SetDopplerScale(p,a) +#define IA3dSource_GetDopplerScale(p,a) (p)->lpVtbl->GetDopplerScale(p,a) +#define IA3dSource_SetDistanceModelScale(p,a) (p)->lpVtbl->SetDistanceModelScale(p,a) +#define IA3dSource_GetDistanceModelScale(p,a) (p)->lpVtbl->GetDistanceModelScale(p,a) +#define IA3dSource_SetEq(p,a) (p)->lpVtbl->SetEq(p,a) +#define IA3dSource_GetEq(p,a) (p)->lpVtbl->GetEq(p,a) +#define IA3dSource_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) +#define IA3dSource_GetPriority(p,a) (p)->lpVtbl->GetPriority(p,a) +#define IA3dSource_SetRenderMode(p,a) (p)->lpVtbl->SetRenderMode(p,a) +#define IA3dSource_GetRenderMode(p,a) (p)->lpVtbl->GetRenderMode(p,a) +#define IA3dSource_GetAudibility(p,a) (p)->lpVtbl->GetAudibility(p,a) +#define IA3dSource_GetOcclusionFactor(p,a) (p)->lpVtbl->GetOcclusionFactor(p,a) +#define IA3dSource_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a) +#define IA3dSource_SetPanValues(p,a,b) (p)->lpVtbl->SetPanValues(p,a,b) +#define IA3dSource_GetPanValues(p,a,b) (p)->lpVtbl->GetPanValues(p,a,b) +#define IA3dSource_SetWaveEvent(p,a,b) (p)->lpVtbl->SetWaveEvent(p,a,b) +#define IA3dSource_ClearWaveEvents(p) (p)->lpVtbl->ClearWaveEvents(p) +#define IA3dSource_SetTransformMode(p,a) (p)->lpVtbl->SetTransformMode(p,a) +#define IA3dSource_GetTransformMode(p,a) (p)->lpVtbl->GetTransformMode(p,a) +#define IA3dSource_SetReflectionDelayScale(p,a) (p)->lpVtbl->SetReflectionDelayScale(p,a) +#define IA3dSource_GetReflectionDelayScale(p,a) (p)->lpVtbl->GetReflectionDelayScale(p,a) +#define IA3dSource_SetReflectionGainScale(p,a) (p)->lpVtbl->SetReflectionGainScale(p,a) +#define IA3dSource_GetReflectionGainScale(p,a) (p)->lpVtbl->GetReflectionGainScale(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IA3dSource_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IA3dSource_AddRef(p) (p)->AddRef() +#define IA3dSource_Release(p) (p)->Release() +#define IA3dSource_LoadWaveFile(p,a) (p)->LoadWaveFile(a) +#define IA3dSource_LoadWaveData(p,a,b) (p)->LoadWaveData(a,b) +#define IA3dSource_AllocateWaveData(p,a) (p)->AllocateWaveData(a) +#define IA3dSource_FreeWaveData(p) (p)->FreeWaveData() +#define IA3dSource_SetWaveFormat(p,a) (p)->SetWaveFormat(a) +#define IA3dSource_GetWaveFormat(p,a) (p)->GetWaveFormat(a) +#define IA3dSource_GetWaveSize(p) (p)->GetWaveSize() +#define IA3dSource_GetType(p,a) (p)->GetType(a) +#define IA3dSource_Lock(p,a,b,c,d,e,f,g) (p)->Lock(a,b,c,d,e,f,g) +#define IA3dSource_Unlock(p,a,b,c,d) (p)->Unlock(a,b,c,d) +#define IA3dSource_Play(p,a) (p)->Play(a) +#define IA3dSource_Stop(p) (p)->Stop() +#define IA3dSource_Rewind(p) (p)->Rewind() +#define IA3dSource_SetWaveTime(p,a) (p)->SetWaveTime(a) +#define IA3dSource_GetWaveTime(p,a) (p)->GetWaveTime(a) +#define IA3dSource_SetWavePosition(p,a) (p)->SetWavePosition(a) +#define IA3dSource_GetWavePosition(p,a) (p)->GetWavePosition(a) +#define IA3dSource_SetPosition3f(p,a,b,c) (p)->SetPosition3f(a,b,c) +#define IA3dSource_GetPosition3f(p,a,b,c) (p)->GetPosition3f(a,b,c) +#define IA3dSource_SetPosition3fv(p,a) (p)->SetPosition3fv(a) +#define IA3dSource_GetPosition3fv(p,a) (p)->GetPosition3fv(a) +#define IA3dSource_SetOrientationAngles3f(p,a,b,c) (p)->SetOrientationAngles3f(a,b,c) +#define IA3dSource_GetOrientationAngles3f(p,a,b,c) (p)->GetOrientationAngles3f(a,b,c) +#define IA3dSource_SetOrientationAngles3fv(p,a) (p)->SetOrientationAngles3fv(a) +#define IA3dSource_GetOrientationAngles3fv(p,a) (p)->GetOrientationAngles3fv(a) +#define IA3dSource_SetOrientation6f(p,a,b,c,d,e,f) (p)->SetOrientation6f(a,b,c,d,e,f) +#define IA3dSource_GetOrientation6f(p,a,b,c,d,e,f) (p)->GetOrientation6f(a,b,c,d,e,f) +#define IA3dSource_SetOrientation6fv(p,a) (p)->SetOrientation6fv(a) +#define IA3dSource_GetOrientation6fv(p,a) (p)->GetOrientation6fv(a) +#define IA3dSource_SetVelocity3f(p,a,b,c) (p)->SetVelocity3f(a,b,c) +#define IA3dSource_GetVelocity3f(p,a,b,c) (p)->GetVelocity3f(a,b,c) +#define IA3dSource_SetVelocity3fv(p,a) (p)->SetVelocity3fv(a) +#define IA3dSource_GetVelocity3fv(p,a) (p)->GetVelocity3fv(a) +#define IA3dSource_SetCone(p,a,b,c) (p)->SetCone(a,b,c) +#define IA3dSource_GetCone(p,a,b,c) (p)->GetCone(a,b,c) +#define IA3dSource_SetMinMaxDistance(p,a,b,c) (p)->SetMinMaxDistance(a,b,c) +#define IA3dSource_GetMinMaxDistance(p,a,b,c) (p)->GetMinMaxDistance(a,b,c) +#define IA3dSource_SetGain(p,a) (p)->SetGain(a) +#define IA3dSource_GetGain(p,a) (p)->GetGain(a) +#define IA3dSource_SetPitch(p,a) (p)->SetPitch(a) +#define IA3dSource_GetPitch(p,a) (p)->GetPitch(a) +#define IA3dSource_SetDopplerScale(p,a) (p)->SetDopplerScale(a) +#define IA3dSource_GetDopplerScale(p,a) (p)->GetDopplerScale(a) +#define IA3dSource_SetDistanceModelScale(p,a) (p)->SetDistanceModelScale(a) +#define IA3dSource_GetDistanceModelScale(p,a) (p)->GetDistanceModelScale(a) +#define IA3dSource_SetEq(p,a) (p)->SetEq(a) +#define IA3dSource_GetEq(p,a) (p)->GetEq(a) +#define IA3dSource_SetPriority(p,a) (p)->SetPriority(a) +#define IA3dSource_GetPriority(p,a) (p)->GetPriority(a) +#define IA3dSource_SetRenderMode(p,a) (p)->SetRenderMode(a) +#define IA3dSource_GetRenderMode(p,a) (p)->GetRenderMode(a) +#define IA3dSource_GetAudibility(p,a) (p)->GetAudibility(a) +#define IA3dSource_GetOcclusionFactor(p,a) (p)->GetOcclusionFactor(a) +#define IA3dSource_GetStatus(p,a) (p)->GetStatus(a) +#define IA3dSource_SetPanValues(p,a,b) (p)->SetPanValues(a,b) +#define IA3dSource_GetPanValues(p,a,b) (p)->GetPanValues(a,b) +#define IA3dSource_SetWaveEvent(p,a,b) (p)->SetWaveEvent(a,b) +#define IA3dSource_ClearWaveEvents(p) (p)->ClearWaveEvents() +#define IA3dSource_SetTransformMode(p,a) (p)->SetTransformMode(a) +#define IA3dSource_GetTransformMode(p,a) (p)->GetTransformMode(a) +#define IA3dSource_SetReflectionDelayScale(p,a) (p)->SetReflectionDelayScale(a) +#define IA3dSource_GetReflectionDelayScale(p,a) (p)->GetReflectionDelayScale(a) +#define IA3dSource_SetReflectionGainScale(p,a) (p)->SetReflectionGainScale(a) +#define IA3dSource_GetReflectionGainScale(p,a) (p)->GetReflectionGainScale(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + + +//=================================================================== +// IA3dListener +// +// There is only one listener in A3D. +//=================================================================== + +// {C398E563-D90B-11d1-90FB-006008A1F441} +DEFINE_GUID(IID_IA3dListener, 0xc398e563, 0xd90b, 0x11d1, 0x90, 0xfb, 0x0, 0x60, 0x8, 0xa1, 0xf4, 0x41); + +#undef INTERFACE +#define INTERFACE IA3dListener + +DECLARE_INTERFACE_(IA3dListener, IUnknown) +{ + // IUnknown Methods. + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID FAR *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IA3dListener Methods. + STDMETHOD(SetPosition3f) (THIS_ A3DVAL, A3DVAL, A3DVAL) PURE; + STDMETHOD(GetPosition3f) (THIS_ LPA3DVAL, LPA3DVAL, LPA3DVAL) PURE; + STDMETHOD(SetPosition3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(GetPosition3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetOrientationAngles3f) (THIS_ A3DVAL, A3DVAL, A3DVAL) PURE; + STDMETHOD(GetOrientationAngles3f) (THIS_ LPA3DVAL, LPA3DVAL, LPA3DVAL) PURE; + STDMETHOD(SetOrientationAngles3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(GetOrientationAngles3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetOrientation6f) (THIS_ A3DVAL, A3DVAL, A3DVAL, A3DVAL, A3DVAL, A3DVAL) PURE; + STDMETHOD(GetOrientation6f) (THIS_ LPA3DVAL, LPA3DVAL, LPA3DVAL, LPA3DVAL, LPA3DVAL, LPA3DVAL) PURE; + STDMETHOD(SetOrientation6fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(GetOrientation6fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(SetVelocity3f) (THIS_ A3DVAL, A3DVAL, A3DVAL) PURE; + STDMETHOD(GetVelocity3f) (THIS_ LPA3DVAL, LPA3DVAL, LPA3DVAL) PURE; + STDMETHOD(SetVelocity3fv) (THIS_ LPA3DVAL) PURE; + STDMETHOD(GetVelocity3fv) (THIS_ LPA3DVAL) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IA3dListener_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IA3dListener_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IA3dListener_Release(p) (p)->lpVtbl->Release(p) +#define IA3dListener_SetPosition3f(p,a,b,c) (p)->lpVtbl->SetPosition3f(p,a,b,c) +#define IA3dListener_GetPosition3f(p,a,b,c) (p)->lpVtbl->GetPosition3f(p,a,b,c) +#define IA3dListener_SetPosition3fv(p,a) (p)->lpVtbl->SetPosition3fv(p,a) +#define IA3dListener_GetPosition3fv(p,a) (p)->lpVtbl->GetPosition3fv(p,a) +#define IA3dListener_SetOrientationAngles3f(p,a,b,c) (p)->lpVtbl->SetOrientationAngles3f(p,a,b,c) +#define IA3dListener_GetOrientationAngles3f(p,a,b,c) (p)->lpVtbl->GetOrientationAngles3f(p,a,b,c) +#define IA3dListener_SetOrientationAngles3fv(p,a) (p)->lpVtbl->SetOrientationAngles3fv(p,a) +#define IA3dListener_GetOrientationAngles3fv(p,a) (p)->lpVtbl->GetOrientationAngles3fv(p,a) +#define IA3dListener_SetOrientation6f(p,a,b,c,d,e,f) (p)->lpVtbl->SetOrientation6f(p,a,b,c,d,e,f) +#define IA3dListener_GetOrientation6f(p,a,b,c,d,e,f) (p)->lpVtbl->GetOrientation6f(p,a,b,c,d,e,f) +#define IA3dListener_SetOrientation6fv(p,a) (p)->lpVtbl->SetOrientation6fv(p,a) +#define IA3dListener_GetOrientation6fv(p,a) (p)->lpVtbl->GetOrientation6fv(p,a) +#define IA3dListener_SetVelocity3f(p,a,b,c) (p)->lpVtbl->SetVelocity3f(p,a,b,c) +#define IA3dListener_GetVelocity3f(p,a,b,c) (p)->lpVtbl->GetVelocity3f(p,a,b,c) +#define IA3dListener_SetVelocity3fv(p,a) (p)->lpVtbl->SetVelocity3fv(p,a) +#define IA3dListener_GetVelocity3fv(p,a) (p)->lpVtbl->GetVelocity3fv(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IA3dListener_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IA3dListener_AddRef(p) (p)->AddRef() +#define IA3dListener_Release(p) (p)->Release() +#define IA3dListener_SetPosition3f(p,a,b,c) (p)->SetPosition3f(a,b,c) +#define IA3dListener_GetPosition3f(p,a,b,c) (p)->GetPosition3f(a,b,c) +#define IA3dListener_SetPosition3fv(p,a) (p)->SetPosition3fv(a) +#define IA3dListener_GetPosition3fv(p,a) (p)->GetPosition3fv(a) +#define IA3dListener_SetOrientationAngles3f(p,a,b,c) (p)->SetOrientationAngles3f(a,b,c) +#define IA3dListener_GetOrientationAngles3f(p,a,b,c) (p)->GetOrientationAngles3f(a,b,c) +#define IA3dListener_SetOrientationAngles3fv(p,a) (p)->SetOrientationAngles3fv(a) +#define IA3dListener_GetOrientationAngles3fv(p,a) (p)->GetOrientationAngles3fv(a) +#define IA3dListener_SetOrientation6f(p,a,b,c,d,e,f) (p)->SetOrientation6f(a,b,c,d,e,f) +#define IA3dListener_GetOrientation6f(p,a,b,c,d,e,f) (p)->GetOrientation6f(a,b,c,d,e,f) +#define IA3dListener_SetOrientation6fv(p,a) (p)->SetOrientation6fv(a) +#define IA3dListener_GetOrientation6fv(p,a) (p)->GetOrientation6fv(a) +#define IA3dListener_SetVelocity3f(p,a,b,c) (p)->SetVelocity3f(a,b,c) +#define IA3dListener_GetVelocity3f(p,a,b,c) (p)->GetVelocity3f(a,b,c) +#define IA3dListener_SetVelocity3fv(p,a) (p)->SetVelocity3fv(a) +#define IA3dListener_GetVelocity3fv(p,a) (p)->GetVelocity3fv(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + + +//=================================================================== +// IA3dList +// +// List of geometry and state data for IA3dGeom. +//=================================================================== + +// {C398E564-D90B-11d1-90FB-006008A1F441} +DEFINE_GUID(IID_IA3dList, 0xc398e564, 0xd90b, 0x11d1, 0x90, 0xfb, 0x0, 0x60, 0x8, 0xa1, 0xf4, 0x41); + +#undef INTERFACE +#define INTERFACE IA3dList + +DECLARE_INTERFACE_(IA3dList, IUnknown) +{ + // IUnknown Methods. + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID FAR *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IA3dList Methods. + STDMETHOD(Begin) (THIS) PURE; + STDMETHOD(End) (THIS) PURE; + STDMETHOD(Call) (THIS) PURE; + STDMETHOD(EnableBoundingVol) (THIS) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IA3dList_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IA3dList_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IA3dList_Release(p) (p)->lpVtbl->Release(p) +#define IA3dList_Begin(p) (p)->lpVtbl->Begin(p) +#define IA3dList_End(p) (p)->lpVtbl->End(p) +#define IA3dList_Call(p) (p)->lpVtbl->Call(p) +#define IA3dList_EnableBoundingVol(p) (p)->lpVtbl->EnableBoundingVol(p) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IA3dList_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IA3dList_AddRef(p) (p)->AddRef() +#define IA3dList_Release(p) (p)->Release() +#define IA3dList_Begin(p) (p)->Begin() +#define IA3dList_End(p) (p)->End() +#define IA3dList_Call(p) (p)->Call() +#define IA3dList_EnableBoundingVol(p) (p)->EnableBoundingVol() +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + + +//=================================================================== +// IA3dMaterial +// +// A material builder. +//=================================================================== + +// {C398E565-D90B-11d1-90FB-006008A1F441} +DEFINE_GUID(IID_IA3dMaterial, 0xc398e565, 0xd90b, 0x11d1, 0x90, 0xfb, 0x0, 0x60, 0x8, 0xa1, 0xf4, 0x41); + +#undef INTERFACE +#define INTERFACE IA3dMaterial + +DECLARE_INTERFACE_(IA3dMaterial, IUnknown) +{ + // IUnknown Methods. + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID FAR *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IA3dMaterial Methods. + STDMETHOD(Load) (THIS_ LPSTR) PURE; + STDMETHOD(Save) (THIS_ LPSTR) PURE; + STDMETHOD(UnSerialize) (THIS_ LPVOID, UINT) PURE; + STDMETHOD(Serialize) (THIS_ LPVOID *, UINT *) PURE; + STDMETHOD(Duplicate) (THIS_ LPA3DMATERIAL *) PURE; + STDMETHOD(SetNameID) (THIS_ LPSTR) PURE; + STDMETHOD(GetNameID) (THIS_ LPSTR, INT) PURE; + STDMETHOD(SelectPreset) (THIS_ DWORD) PURE; + STDMETHOD(GetClosestPreset) (THIS_ LPDWORD) PURE; + STDMETHOD(SetReflectance) (THIS_ A3DVAL, A3DVAL) PURE; + STDMETHOD(GetReflectance) (THIS_ LPA3DVAL, LPA3DVAL) PURE; + STDMETHOD(SetTransmittance) (THIS_ A3DVAL, A3DVAL) PURE; + STDMETHOD(GetTransmittance) (THIS_ LPA3DVAL, LPA3DVAL) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IA3dMaterial_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IA3dMaterial_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IA3dMaterial_Release(p) (p)->lpVtbl->Release(p) +#define IA3dMaterial_Load(p,a) (p)->lpVtbl->Load(p,a) +#define IA3dMaterial_Save(p,a) (p)->lpVtbl->Save(p,a) +#define IA3dMaterial_UnSerialize(p,a,b) (p)->lpVtbl->UnSerialize(p,a,b) +#define IA3dMaterial_Serialize(p,a,b) (p)->lpVtbl->Serialize(p,a,b) +#define IA3dMaterial_Duplicate(p,a) (p)->lpVtbl->Duplicate(p,a) +#define IA3dMaterial_SetNameID(p,a) (p)->lpVtbl->SetNameID(p,a) +#define IA3dMaterial_GetNameID(p,a,b) (p)->lpVtbl->GetNameID(p,a,b) +#define IA3dMaterial_SelectPreset(p,a) (p)->lpVtbl->SelectPreset(p,a) +#define IA3dMaterial_GetClosestPreset(p,a) (p)->lpVtbl->GetClosestPreset(p,a) +#define IA3dMaterial_SetReflectance(p,a,b) (p)->lpVtbl->SetReflectance(p,a,b) +#define IA3dMaterial_GetReflectance(p,a,b) (p)->lpVtbl->GetReflectance(p,a,b) +#define IA3dMaterial_SetTransmittance(p,a,b) (p)->lpVtbl->SetTransmittance(p,a,b) +#define IA3dMaterial_GetTransmittance(p,a,b) (p)->lpVtbl->GetTransmittance(p,a,b) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IA3dMaterial_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IA3dMaterial_AddRef(p) (p)->AddRef() +#define IA3dMaterial_Release(p) (p)->Release() +#define IA3dMaterial_Load(p,a) (p)->Load(a) +#define IA3dMaterial_Save(p,a) (p)->Save(a) +#define IA3dMaterial_UnSerialize(p,a,b) (p)->UnSerialize(a,b) +#define IA3dMaterial_Serialize(p,a,b) (p)->Serialize(a,b) +#define IA3dMaterial_Duplicate(p,a) (p)->Duplicate(a) +#define IA3dMaterial_SetNameID(p,a) (p)->SetNameID(a) +#define IA3dMaterial_GetNameID(p,a,b) (p)->GetNameID(a,b) +#define IA3dMaterial_SelectPreset(p,a) (p)->SelectPreset(a) +#define IA3dMaterial_GetClosestPreset(p,a) (p)->GetClosestPreset(a) +#define IA3dMaterial_SetReflectance(p,a,b) (p)->SetReflectance(a,b) +#define IA3dMaterial_GetReflectance(p,a,b) (p)->GetReflectance(a,b) +#define IA3dMaterial_SetTransmittance(p,a,b) (p)->SetTransmittance(a,b) +#define IA3dMaterial_GetTransmittance(p,a,b) (p)->GetTransmittance(a,b) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +//=================================================================== +// Error Codes +// +// Use macros A3DERROR_CODE(code) for errors and A3DSUCCESS_CODE(code) +// for success codes or predefined universal COM success and failure +// code. +// +// All success codes should be mutally exclusive to all other success other. +// +// All error codes should be mutually exclusive to all other error codes. +// +//=================================================================== + +#define A3DERROR_CODE(code) MAKE_HRESULT(1,FACILITY_ITF, code) +#define A3DSUCCESS_CODE(code) MAKE_HRESULT(0,FACILITY_ITF, code) + +#define A3DERROR_MEMORY_ALLOCATION A3DERROR_CODE(1) +#define A3DERROR_FAILED_CREATE_PRIMARY_BUFFER A3DERROR_CODE(2) +#define A3DERROR_FAILED_CREATE_SECONDARY_BUFFER A3DERROR_CODE(3) +#define A3DERROR_FAILED_INIT_A3D_DRIVER A3DERROR_CODE(4) +#define A3DERROR_FAILED_QUERY_DIRECTSOUND A3DERROR_CODE(5) +#define A3DERROR_FAILED_QUERY_A3D3 A3DERROR_CODE(6) +#define A3DERROR_FAILED_INIT_A3D3 A3DERROR_CODE(7) +#define A3DERROR_FAILED_QUERY_A3D2 A3DERROR_CODE(8) +#define A3DERROR_FAILED_FILE_OPEN A3DERROR_CODE(9) +#define A3DERROR_FAILED_CREATE_SOUNDBUFFER A3DERROR_CODE(10) +#define A3DERROR_FAILED_QUERY_3DINTERFACE A3DERROR_CODE(11) +#define A3DERROR_FAILED_LOCK_BUFFER A3DERROR_CODE(12) +#define A3DERROR_FAILED_UNLOCK_BUFFER A3DERROR_CODE(13) +#define A3DERROR_UNRECOGNIZED_FORMAT A3DERROR_CODE(14) +#define A3DERROR_NO_WAVE_DATA A3DERROR_CODE(15) +#define A3DERROR_UNKNOWN_PLAYMODE A3DERROR_CODE(16) +#define A3DERROR_FAILED_PLAY A3DERROR_CODE(17) +#define A3DERROR_FAILED_STOP A3DERROR_CODE(18) +#define A3DERROR_NEEDS_FORMAT_INFORMATION A3DERROR_CODE(19) +#define A3DERROR_FAILED_ALLOCATE_WAVEDATA A3DERROR_CODE(20) +#define A3DERROR_NOT_VALID_SOURCE A3DERROR_CODE(21) +#define A3DERROR_FAILED_DUPLICATION A3DERROR_CODE(22) +#define A3DERROR_FAILED_INIT A3DERROR_CODE(23) +#define A3DERROR_FAILED_SETCOOPERATIVE_LEVEL A3DERROR_CODE(24) +#define A3DERROR_FAILED_INIT_QUERIED_INTERFACE A3DERROR_CODE(25) +#define A3DERROR_GEOMETRY_INPUT_OUTSIDE_BEGIN_END_BLOCK A3DERROR_CODE(26) +#define A3DERROR_INVALID_NORMAL A3DERROR_CODE(27) +#define A3DERROR_END_BEFORE_VALID_BEGIN_BLOCK A3DERROR_CODE(28) +#define A3DERROR_INVALID_BEGIN_MODE A3DERROR_CODE(29) +#define A3DERROR_INVALID_ARGUMENT A3DERROR_CODE(30) +#define A3DERROR_INVALID_INDEX A3DERROR_CODE(31) +#define A3DERROR_INVALID_VERTEX_INDEX A3DERROR_CODE(32) +#define A3DERROR_INVALID_PRIMITIVE_INDEX A3DERROR_CODE(33) +#define A3DERROR_MIXING_2D_AND_3D_MODES A3DERROR_CODE(34) +#define A3DERROR_2DWALL_REQUIRES_EXACTLY_ONE_LINE A3DERROR_CODE(35) +#define A3DERROR_NO_PRIMITIVES_DEFINED A3DERROR_CODE(36) +#define A3DERROR_PRIMITIVES_NON_PLANAR A3DERROR_CODE(37) +#define A3DERROR_PRIMITIVES_OVERLAPPING A3DERROR_CODE(38) +#define A3DERROR_PRIMITIVES_NOT_ADJACENT A3DERROR_CODE(39) +#define A3DERROR_OBJECT_NOT_FOUND A3DERROR_CODE(40) +#define A3DERROR_ROOM_HAS_NO_SHELL_WALLS A3DERROR_CODE(41) +#define A3DERROR_WALLS_DO_NOT_ENCLOSE_ROOM A3DERROR_CODE(42) +#define A3DERROR_INVALID_WALL A3DERROR_CODE(43) +#define A3DERROR_ROOM_HAS_LESS_THAN_4SHELL_WALLS A3DERROR_CODE(44) +#define A3DERROR_ROOM_HAS_LESS_THAN_3UNIQUE_NORMALS A3DERROR_CODE(45) +#define A3DERROR_INTERSECTING_WALL_EDGES A3DERROR_CODE(46) +#define A3DERROR_INVALID_ROOM A3DERROR_CODE(47) +#define A3DERROR_SCENE_HAS_ROOMS_INSIDE_ANOTHER_ROOMS A3DERROR_CODE(48) +#define A3DERROR_SCENE_HAS_OVERLAPPING_STATIC_ROOMS A3DERROR_CODE(49) +#define A3DERROR_DYNAMIC_OBJ_UNSUPPORTED A3DERROR_CODE(50) +#define A3DERROR_DIR_AND_UP_VECTORS_NOT_PERPENDICULAR A3DERROR_CODE(51) +#define A3DERROR_INVALID_ROOM_INDEX A3DERROR_CODE(52) +#define A3DERROR_INVALID_WALL_INDEX A3DERROR_CODE(53) +#define A3DERROR_SCENE_INVALID A3DERROR_CODE(54) +#define A3DERROR_UNIMPLEMENTED_FUNCTION A3DERROR_CODE(55) +#define A3DERROR_NO_ROOMS_IN_SCENE A3DERROR_CODE(56) +#define A3DERROR_2D_GEOMETRY_UNIMPLEMENTED A3DERROR_CODE(57) +#define A3DERROR_OPENING_NOT_WALL_COPLANAR A3DERROR_CODE(58) +#define A3DERROR_OPENING_NOT_VALID A3DERROR_CODE(59) +#define A3DERROR_INVALID_OPENING_INDEX A3DERROR_CODE(60) +#define A3DERROR_FEATURE_NOT_REQUESTED A3DERROR_CODE(61) +#define A3DERROR_FEATURE_NOT_SUPPORTED A3DERROR_CODE(62) +#define A3DERROR_FUNCTION_NOT_VALID_BEFORE_INIT A3DERROR_CODE(63) +#define A3DERROR_INVALID_NUMBER_OF_CHANNELS A3DERROR_CODE(64) +#define A3DERROR_SOURCE_IN_NATIVE_MODE A3DERROR_CODE(65) +#define A3DERROR_SOURCE_IN_A3D_MODE A3DERROR_CODE(66) +#define A3DERROR_BBOX_CANNOT_ENABLE_AFTER_BEGIN_LIST_CALL A3DERROR_CODE(67) +#define A3DERROR_CANNOT_CHANGE_FORMAT_FOR_ALLOCATED_BUFFER A3DERROR_CODE(68) +#define A3DERROR_FAILED_QUERY_DIRECTSOUNDNOTIFY A3DERROR_CODE(69) +#define A3DERROR_DIRECTSOUNDNOTIFY_FAILED A3DERROR_CODE(70) +#define A3DERROR_RESOURCE_MANAGER_ALWAYS_ON A3DERROR_CODE(71) +#define A3DERROR_CLOSED_LIST_CANNOT_BE_CHANGED A3DERROR_CODE(72) +#define A3DERROR_END_CALLED_BEFORE_BEGIN A3DERROR_CODE(73) +#define A3DERROR_UNMANAGED_BUFFER A3DERROR_CODE(74) +#define A3DERROR_COORD_SYSTEM_CAN_ONLY_BE_SET_ONCE A3DERROR_CODE(75) + +#ifdef __cplusplus +}; +#endif + +#endif // #ifndef _IA3DAPI_H_ + diff --git a/D3Launch/res/Anim0.BMP b/D3Launch/res/Anim0.BMP new file mode 100644 index 00000000..0884f8f6 Binary files /dev/null and b/D3Launch/res/Anim0.BMP differ diff --git a/D3Launch/res/Anim1.BMP b/D3Launch/res/Anim1.BMP new file mode 100644 index 00000000..3df63bef Binary files /dev/null and b/D3Launch/res/Anim1.BMP differ diff --git a/D3Launch/res/Anim2.BMP b/D3Launch/res/Anim2.BMP new file mode 100644 index 00000000..b7601365 Binary files /dev/null and b/D3Launch/res/Anim2.BMP differ diff --git a/D3Launch/res/Anim3.BMP b/D3Launch/res/Anim3.BMP new file mode 100644 index 00000000..30a580ed Binary files /dev/null and b/D3Launch/res/Anim3.BMP differ diff --git a/D3Launch/res/Anim4.bmp b/D3Launch/res/Anim4.bmp new file mode 100644 index 00000000..b8a6afdf Binary files /dev/null and b/D3Launch/res/Anim4.bmp differ diff --git a/D3Launch/res/Anim5.bmp b/D3Launch/res/Anim5.bmp new file mode 100644 index 00000000..904a68b3 Binary files /dev/null and b/D3Launch/res/Anim5.bmp differ diff --git a/D3Launch/res/Anim6.bmp b/D3Launch/res/Anim6.bmp new file mode 100644 index 00000000..adc7e8a4 Binary files /dev/null and b/D3Launch/res/Anim6.bmp differ diff --git a/D3Launch/res/Anim7.bmp b/D3Launch/res/Anim7.bmp new file mode 100644 index 00000000..69b247db Binary files /dev/null and b/D3Launch/res/Anim7.bmp differ diff --git a/D3Launch/res/Anim8.bmp b/D3Launch/res/Anim8.bmp new file mode 100644 index 00000000..aff09ae5 Binary files /dev/null and b/D3Launch/res/Anim8.bmp differ diff --git a/D3Launch/res/D3Launch.ico b/D3Launch/res/D3Launch.ico new file mode 100644 index 00000000..389d6b52 Binary files /dev/null and b/D3Launch/res/D3Launch.ico differ diff --git a/D3Launch/res/D3Launch.rc2 b/D3Launch/res/D3Launch.rc2 new file mode 100644 index 00000000..515d5492 --- /dev/null +++ b/D3Launch/res/D3Launch.rc2 @@ -0,0 +1,19 @@ +// +// D3LAUNCH.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// +StartupSnd WAVE res\running.wav +BulbFlickerSnd WAVE res\bulbstc.wav +NormalBtnPressedSnd WAVE res\breath.wav +NormalBtnLitSnd WAVE res\briefingtype1.wav +PowerBtnPressedSnd WAVE res\breath.wav +PowerBtnLitSnd WAVE res\fanE.wav diff --git a/D3Launch/res/DirectxD.bmp b/D3Launch/res/DirectxD.bmp new file mode 100644 index 00000000..565f0c24 Binary files /dev/null and b/D3Launch/res/DirectxD.bmp differ diff --git a/D3Launch/res/DirectxM.bmp b/D3Launch/res/DirectxM.bmp new file mode 100644 index 00000000..1ec58c1c Binary files /dev/null and b/D3Launch/res/DirectxM.bmp differ diff --git a/D3Launch/res/DirectxU.bmp b/D3Launch/res/DirectxU.bmp new file mode 100644 index 00000000..e06544cd Binary files /dev/null and b/D3Launch/res/DirectxU.bmp differ diff --git a/D3Launch/res/DirectxX.bmp b/D3Launch/res/DirectxX.bmp new file mode 100644 index 00000000..68481f4a Binary files /dev/null and b/D3Launch/res/DirectxX.bmp differ diff --git a/D3Launch/res/HelpD.bmp b/D3Launch/res/HelpD.bmp new file mode 100644 index 00000000..487fd86b Binary files /dev/null and b/D3Launch/res/HelpD.bmp differ diff --git a/D3Launch/res/HelpM.bmp b/D3Launch/res/HelpM.bmp new file mode 100644 index 00000000..72dbb047 Binary files /dev/null and b/D3Launch/res/HelpM.bmp differ diff --git a/D3Launch/res/HelpU.bmp b/D3Launch/res/HelpU.bmp new file mode 100644 index 00000000..b1e8df5b Binary files /dev/null and b/D3Launch/res/HelpU.bmp differ diff --git a/D3Launch/res/LightD.BMP b/D3Launch/res/LightD.BMP new file mode 100644 index 00000000..d170eb8c Binary files /dev/null and b/D3Launch/res/LightD.BMP differ diff --git a/D3Launch/res/LightM.BMP b/D3Launch/res/LightM.BMP new file mode 100644 index 00000000..4f869d11 Binary files /dev/null and b/D3Launch/res/LightM.BMP differ diff --git a/D3Launch/res/LightU.BMP b/D3Launch/res/LightU.BMP new file mode 100644 index 00000000..d170eb8c Binary files /dev/null and b/D3Launch/res/LightU.BMP differ diff --git a/D3Launch/res/OutrageD.BMP b/D3Launch/res/OutrageD.BMP new file mode 100644 index 00000000..187a4260 Binary files /dev/null and b/D3Launch/res/OutrageD.BMP differ diff --git a/D3Launch/res/OutrageM.BMP b/D3Launch/res/OutrageM.BMP new file mode 100644 index 00000000..f1771bc4 Binary files /dev/null and b/D3Launch/res/OutrageM.BMP differ diff --git a/D3Launch/res/OutrageU.BMP b/D3Launch/res/OutrageU.BMP new file mode 100644 index 00000000..c7ae8192 Binary files /dev/null and b/D3Launch/res/OutrageU.BMP differ diff --git a/D3Launch/res/Play.bmp b/D3Launch/res/Play.bmp new file mode 100644 index 00000000..ce5f1d25 Binary files /dev/null and b/D3Launch/res/Play.bmp differ diff --git a/D3Launch/res/PlayD.bmp b/D3Launch/res/PlayD.bmp new file mode 100644 index 00000000..2ed9f14e Binary files /dev/null and b/D3Launch/res/PlayD.bmp differ diff --git a/D3Launch/res/PlayM.bmp b/D3Launch/res/PlayM.bmp new file mode 100644 index 00000000..0732b021 Binary files /dev/null and b/D3Launch/res/PlayM.bmp differ diff --git a/D3Launch/res/PlayX.BMP b/D3Launch/res/PlayX.BMP new file mode 100644 index 00000000..145d75af Binary files /dev/null and b/D3Launch/res/PlayX.BMP differ diff --git a/D3Launch/res/Pxod.bmp b/D3Launch/res/Pxod.bmp new file mode 100644 index 00000000..8cc16ada Binary files /dev/null and b/D3Launch/res/Pxod.bmp differ diff --git a/D3Launch/res/Pxom.bmp b/D3Launch/res/Pxom.bmp new file mode 100644 index 00000000..d29b6ad3 Binary files /dev/null and b/D3Launch/res/Pxom.bmp differ diff --git a/D3Launch/res/Pxou.bmp b/D3Launch/res/Pxou.bmp new file mode 100644 index 00000000..3e3b044b Binary files /dev/null and b/D3Launch/res/Pxou.bmp differ diff --git a/D3Launch/res/QuitD.bmp b/D3Launch/res/QuitD.bmp new file mode 100644 index 00000000..3a49e6ac Binary files /dev/null and b/D3Launch/res/QuitD.bmp differ diff --git a/D3Launch/res/QuitM.bmp b/D3Launch/res/QuitM.bmp new file mode 100644 index 00000000..575cdc33 Binary files /dev/null and b/D3Launch/res/QuitM.bmp differ diff --git a/D3Launch/res/QuitU.bmp b/D3Launch/res/QuitU.bmp new file mode 100644 index 00000000..2c9af2c6 Binary files /dev/null and b/D3Launch/res/QuitU.bmp differ diff --git a/D3Launch/res/ReadMeD.BMP b/D3Launch/res/ReadMeD.BMP new file mode 100644 index 00000000..565f0c24 Binary files /dev/null and b/D3Launch/res/ReadMeD.BMP differ diff --git a/D3Launch/res/ReadMeM.BMP b/D3Launch/res/ReadMeM.BMP new file mode 100644 index 00000000..1ec58c1c Binary files /dev/null and b/D3Launch/res/ReadMeM.BMP differ diff --git a/D3Launch/res/ReadMeU.BMP b/D3Launch/res/ReadMeU.BMP new file mode 100644 index 00000000..e06544cd Binary files /dev/null and b/D3Launch/res/ReadMeU.BMP differ diff --git a/D3Launch/res/ReadMeX.BMP b/D3Launch/res/ReadMeX.BMP new file mode 100644 index 00000000..68481f4a Binary files /dev/null and b/D3Launch/res/ReadMeX.BMP differ diff --git a/D3Launch/res/SetupD.bmp b/D3Launch/res/SetupD.bmp new file mode 100644 index 00000000..2ed9f14e Binary files /dev/null and b/D3Launch/res/SetupD.bmp differ diff --git a/D3Launch/res/SetupM.bmp b/D3Launch/res/SetupM.bmp new file mode 100644 index 00000000..0732b021 Binary files /dev/null and b/D3Launch/res/SetupM.bmp differ diff --git a/D3Launch/res/SetupU.bmp b/D3Launch/res/SetupU.bmp new file mode 100644 index 00000000..ce5f1d25 Binary files /dev/null and b/D3Launch/res/SetupU.bmp differ diff --git a/D3Launch/res/SetupX.bmp b/D3Launch/res/SetupX.bmp new file mode 100644 index 00000000..145d75af Binary files /dev/null and b/D3Launch/res/SetupX.bmp differ diff --git a/D3Launch/res/UninstallD.bmp b/D3Launch/res/UninstallD.bmp new file mode 100644 index 00000000..565f0c24 Binary files /dev/null and b/D3Launch/res/UninstallD.bmp differ diff --git a/D3Launch/res/UninstallM.bmp b/D3Launch/res/UninstallM.bmp new file mode 100644 index 00000000..1ec58c1c Binary files /dev/null and b/D3Launch/res/UninstallM.bmp differ diff --git a/D3Launch/res/UninstallU.bmp b/D3Launch/res/UninstallU.bmp new file mode 100644 index 00000000..e06544cd Binary files /dev/null and b/D3Launch/res/UninstallU.bmp differ diff --git a/D3Launch/res/UninstallX.bmp b/D3Launch/res/UninstallX.bmp new file mode 100644 index 00000000..68481f4a Binary files /dev/null and b/D3Launch/res/UninstallX.bmp differ diff --git a/D3Launch/res/UpdateD.bmp b/D3Launch/res/UpdateD.bmp new file mode 100644 index 00000000..2ed9f14e Binary files /dev/null and b/D3Launch/res/UpdateD.bmp differ diff --git a/D3Launch/res/UpdateM.bmp b/D3Launch/res/UpdateM.bmp new file mode 100644 index 00000000..0732b021 Binary files /dev/null and b/D3Launch/res/UpdateM.bmp differ diff --git a/D3Launch/res/UpdateU.bmp b/D3Launch/res/UpdateU.bmp new file mode 100644 index 00000000..ce5f1d25 Binary files /dev/null and b/D3Launch/res/UpdateU.bmp differ diff --git a/D3Launch/res/UpdateX.bmp b/D3Launch/res/UpdateX.bmp new file mode 100644 index 00000000..145d75af Binary files /dev/null and b/D3Launch/res/UpdateX.bmp differ diff --git a/D3Launch/res/bitmap1.bmp b/D3Launch/res/bitmap1.bmp new file mode 100644 index 00000000..b2aae99d Binary files /dev/null and b/D3Launch/res/bitmap1.bmp differ diff --git a/D3Launch/res/breath.wav b/D3Launch/res/breath.wav new file mode 100644 index 00000000..05549c38 Binary files /dev/null and b/D3Launch/res/breath.wav differ diff --git a/D3Launch/res/briefingtype1.wav b/D3Launch/res/briefingtype1.wav new file mode 100644 index 00000000..e9f14673 Binary files /dev/null and b/D3Launch/res/briefingtype1.wav differ diff --git a/D3Launch/res/bulbstc.wav b/D3Launch/res/bulbstc.wav new file mode 100644 index 00000000..6ccd3219 Binary files /dev/null and b/D3Launch/res/bulbstc.wav differ diff --git a/D3Launch/res/fanE.wav b/D3Launch/res/fanE.wav new file mode 100644 index 00000000..59129785 Binary files /dev/null and b/D3Launch/res/fanE.wav differ diff --git a/D3Launch/res/palette.bmp b/D3Launch/res/palette.bmp new file mode 100644 index 00000000..9a51a3a6 Binary files /dev/null and b/D3Launch/res/palette.bmp differ diff --git a/D3Launch/res/running.wav b/D3Launch/res/running.wav new file mode 100644 index 00000000..4666f53f Binary files /dev/null and b/D3Launch/res/running.wav differ diff --git a/D3Launch/resource.h b/D3Launch/resource.h new file mode 100644 index 00000000..b3f055bf --- /dev/null +++ b/D3Launch/resource.h @@ -0,0 +1,314 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by D3Launch.rc +// +#define IDS_UPDATEDLG_USERMSG1 1 +#define IDS_UPDATEDLG_USERMSG2 2 +#define IDS_D3LAUNCH_DLGTITLE 3 +#define IDS_D3LAUNCH_URL_ERR1 4 +#define IDS_D3LAUNCH_URL_ERR2 5 +#define IDS_D3LAUNCH_URL_ERR3 6 +#define IDS_D3LAUNCH_URL_ERR4 7 +#define IDS_D3LAUNCH_URL_ERR5 8 +#define IDS_D3LAUNCH_URL_ERR6 9 +#define IDS_D3LAUNCH_URL_ERR7 10 +#define IDS_D3LAUNCH_URL_ERR8 11 +#define IDS_D3LAUNCH_URL_ERR9 12 +#define IDS_D3LAUNCH_URL_ERR10 13 +#define IDS_D3LAUNCH_URL_ERR11 14 +#define IDS_D3LAUNCH_URL_ERR12 15 +#define IDS_D3LAUNCHDLG_NODD 16 +#define IDS_D3LAUNCHDLG_NODDT 17 +#define IDS_D3LAUNCHDLG_SETUP 18 +#define IDS_D3LAUNCHDLG_RM_ERR 19 +#define IDS_D3LAUNCHDLG_LNCH_ERR 20 +#define IDS_3D_DETECT_NO3D 21 +#define IDS_AUDIOTAB_A3D1 22 +#define IDS_AUDIOTAB_A3D2 23 +#define IDS_AUDIOTAB_NO_SOUND 24 +#define IDS_JOYSTICKTAB_ERR1 25 +#define IDS_JOYSTICKTAB_NONE 26 +#define IDS_UPDATEDLG_GVN_MSG1 27 +#define IDS_UPDATEDLG_NO_CON 28 +#define IDS_UPDATEDLG_ERROR 29 +#define IDS_UPDATEDLG_GVN_MSG2 30 +#define IDS_UPDATEDLG_NO_DL 31 +#define IDS_UPDATEDLG_NO_FIND 32 +#define IDS_UPDATEDLG_WAIT 33 +#define IDS_UPDATEDLG_SRV 34 +#define IDS_UPDATEDLG_UTD 35 +#define IDS_UPDATEDLG_UTDT 36 +#define IDS_UPDATEDLG_YES_ERR1 37 +#define IDS_UPDATEDLG_PF_ERR1 38 +#define IDS_UPDATEDLG_PATCHING 39 +#define IDS_UPDATEDLG_GET_FILE 40 +#define IDS_UPDATEDLG_CANT_PATCH 41 +#define IDS_UPDATEDLG_SKIPPING 42 +#define IDS_UPDATEDLG_PATCH_OK 43 +#define IDS_UPDATEDLG_SUCCESS 44 +#define IDS_UPDATEDLG_NO_PATCH_LIB 45 +#define IDS_UPDATEDLG_DL_FILE 46 +#define IDS_UPDATEDLG_INIT_CON 47 +#define IDS_UPDATEDLG_WS_ERR 48 +#define IDS_UPDATEDLG_CON_OK 49 +#define IDS_UPDATEDLG_CON_SHUTDOWN 50 +#define IDS_UPDATEDLG_WAITING 51 +#define IDS_SPEEDTAB_LOW 52 +#define IDS_SPEEDTAB_MEDIUM 53 +#define IDS_SPEEDTAB_HIGH 54 +#define IDS_SPEEDTAB_VERY_HIGH 55 +#define IDS_UPDATEDLG_LNCH_UPD1 56 +#define IDS_UPDATEDLG_LNCH_UPD2 57 +#define IDS_UPDATEDLG_LNCH_UPD3 58 +#define IDS_UPDATEDLG_LNCH_UPD_TITLE 59 +#define IDS_UPDATEDLG_BEG_PATCH 60 +#define IDS_UPDATEDLG_PATCH_COMPLETE 61 +#define IDS_UPDATEDLG_PATCH_FAILED 62 +#define IDS_UPDATEDLG_PATCH_ERROR 63 +#define IDS_UPDATEDLG_PROCESSING 64 +#define IDS_UPDATEDLG_FILE_COMPLETE 65 +#define IDS_UPDATEDLG_SEARCHING 66 +#define IDS_UPDATEDLG_WNDMSG_MAIN 67 +#define IDS_UPDATEDLG_WNDMSG_STATUS 68 +#define IDS_UPDATEDLG_USERMSG3 69 +#define IDS_SITESELECTDLG_SITE_NAME 70 +#define IDS_SITESELECTDLG_SITE_ADDRESS 71 +#define IDS_SITESELECTDLG_SITE_LOCATION 72 +#define IDS_SITESELECTDLG_MUST_SELECT 73 +#define IDS_SITESELECTDLG_SELECT_TITLE 74 +#define IDS_UPDATEDLG_BADPARMS 75 +#define IDS_UPDATEDLG_CANT_WRITE_FILE 76 +#define IDS_UPDATEDLG_CANT_PARSE_URL 77 +#define IDS_UPDATEDLG_BAD_FILE_OR_DIR 78 +#define IDS_UPDATEDLG_HOST_NOT_FOUND 79 +#define IDS_UPDATEDLG_NO_MEMORY 80 +#define IDS_UPDATEDLG_CANCELLED 81 +#define IDS_UPDATEDLG_UNKNOWN_ERROR 82 +#define IDS_UPDATEDLG_DOWNLOAD_ERROR 83 +#define IDS_SITESELECTDLG_PARSE_ERROR 84 +#define IDS_UPDATEDLG_DONE_UPDATING 85 +#define IDS_UPDATEDLG_CONTINUE_MSG 86 +#define IDS_UPDATEDLG_NO_MOTD 87 +#define IDS_UPDATEDLG_DL_MOTD 88 +#define IDS_UPDATEDLG_GOT_MOTD 89 +#define IDS_UPDATEDLG_NODL_MOTD 90 +#define IDS_AUDIOTAB_CARD_MISSING 91 +#define IDS_AUDIOTAB_WARNING 92 +#define IDS_DIRECTXTAB_OK 93 +#define IDS_D3LAUNCH_NO_CD 94 +#define IDS_D3LAUNCH_CD_ERROR 95 +#define IDS_DIRECTXTAB_NTMSG 96 +#define IDS_DIRECTXTAB_NTNOTICE 97 +#define IDS_DIRECTXTAB_LOAD_ERROR 98 +#define IDS_D3LAUNCHDLG_NO_UNINSTALL 99 +#define IDS_D3LAUNCHDLG_COULDNT_UNINSTALL 100 +#define IDS_D3LAUNCHDLG_WARNING_PROMPT 101 +#define IDD_D3LAUNCH_DIALOG 102 +#define IDS_D3LAUNCHDLG_WARNING_TITLE 102 +#define IDS_D3LAUNCHDLG_UNINSTALL_ERROR 103 +#define IDS_D3LAUNCHDLG_PLAY 104 +#define IDS_D3LAUNCHDLG_PLAY_BTN 104 +#define IDS_D3LAUNCHDLG_SETUP_BTN 105 +#define IDS_D3LAUNCHDLG_UPDATE_BTN 106 +#define IDS_D3LAUNCHDLG_README_BTN 107 +#define IDS_D3LAUNCHDLG_DIRECTX_BTN 108 +#define IDS_D3LAUNCHDLG_UNINSTALL_BTN 109 +#define IDS_D3LAUNCHDLG_INSTALL_BTN 110 +#define IDS_D3LAUNCHDLG_STRAIGHTTOSETUP_MSG 111 +#define IDS_D3LAUNCHDLG_STRAIGHTTOSETUP_TITLE 112 +#define IDS_D3LAUNCHDLG_PLAY_WARNING_MSG 113 +#define IDS_D3LAUNCHDLG_FILE_NOT_FOUND 114 +#define IDS_D3LAUNCH_NO_HELP 115 +#define IDS_SPEEDTAB_SPEED_PROMPT 116 +#define IDS_SPEEDTAB_SPEED_TITLE 117 +#define IDS_D3LAUNCHDLG_WEBPAGE_BTN 118 +#define IDS_D3LAUNCHDLG_PXO_BTN 119 +#define IDS_D3LAUNCHDLG_NO_RENDERER_MSG 120 +#define IDS_D3LAUNCHDLG_NO_RENDERER_TITLE 121 +#define IDS_D3LAUNCHDLG_DEMO_ONLY_MSG 122 +#define IDS_D3LAUNCHDLG_DEMO_ONLY_TITLE 123 +#define IDS_D3LAUNCH_DEMO_DLGTITLE 124 +#define IDS_VIDEOTAB_DXVERSION_TITLE 125 +#define IDS_VIDEOTAB_DXVERSION_MSG 126 +#define IDS_D3LAUNCHDLG_DXVERSION_TITLE 127 +#define IDR_MAINFRAME 128 +#define IDS_D3LAUNCHDLG_DXVERSION_MSG 128 +#define IDD_UPDATE_DIALOG 129 +#define IDS_D3LAUNCHDLG_NOMEM_TITLE 129 +#define IDS_D3LAUNCHDLG_NOMEM_MSG 130 +#define IDS_PLEASE_WAIT_MSG 131 +#define IDS_VIDEOTAB_SCANNING 132 +#define IDS_AUDIOTAB_SCANNING 133 +#define IDB_D3LAUNCH_BG 134 +#define IDS_JOYSTICKTAB_SCANNING 134 +#define IDD_PROPPAGE_JOYSTICK 135 +#define IDS_VIDEOTAB_MTOD_MSG 135 +#define IDD_PROPPAGE_VIDEO 136 +#define IDS_VIDEOTAB_MTOD_TITLE 136 +#define IDD_PROPPAGE_AUDIO 137 +#define IDS_SPEEDTAB_NOT_DETECTED 137 +#define IDD_PROPPAGE_SPEED 138 +#define IDS_UPDATEDLG_NOREGVER_MSG 138 +#define IDD_PROPPAGE_NETWORK 139 +#define IDS_UPDATEDLG_NOREGVER_TITLE 139 +#define IDD_WAIT_DIALOG 140 +#define IDS_DIRECTXTAB_UPD_REC 140 +#define IDS_SPEEDTAB_CUSTOM 141 +#define IDS_D3LAUNCHDLG_SPD_MSG 142 +#define IDS_D3LAUNCHDLG_SPD_TITLE 143 +#define IDS_D3LAUNCHDLG_LAUNCH_ERRMSG 144 +#define IDS_D3LAUNCHDLG_CONTEST_MSG 145 +#define IDS_D3LAUNCHDLG_CONTEST_TITLE 146 +#define IDS_D3LAUNCHDLG_DXERR_SUCCESS 147 +#define IDS_D3LAUNCHDLG_DXERR_SUCCESS_RESTART 148 +#define IDS_D3LAUNCHDLG_DXERR_BADSOURCESIZE 149 +#define IDS_D3LAUNCHDLG_DXERR_BADSOURCETIME 150 +#define IDS_D3LAUNCHDLG_DXERR_BADWINDOWSVERSION 151 +#define IDS_D3LAUNCHDLG_DXERR_CANTFINDDIR 152 +#define IDS_D3LAUNCHDLG_DXERR_CANTFINDINF 153 +#define IDS_D3LAUNCHDLG_DXERR_INTERNAL 154 +#define IDS_D3LAUNCHDLG_DXERR_NOCOPY 155 +#define IDS_D3LAUNCHDLG_DXERR_NOTPREINSTALLEDONNT 156 +#define IDS_D3LAUNCHDLG_DXERR_OUTOFDISKSPACE 157 +#define IDS_D3LAUNCHDLG_DXERR_SOURCEFILENOTFOUND 158 +#define IDS_D3LAUNCHDLG_DXERR_UNKNOWNOS 159 +#define IDS_D3LAUNCHDLG_DXERR_USERHITCANCEL 160 +#define IDS_D3LAUNCHDLG_DXERR_TITLE 161 +#define IDD_PROPPAGE_KEYBOARD 162 +#define IDS_D3LAUNCHDLG_DSETUP_ERR_MSG1 162 +#define IDD_MESSAGE_WINDOW 163 +#define IDS_D3LAUNCHDLG_DSETUP_ERR_MSG2 163 +#define IDD_SITE_SELECTION_DIALOG 164 +#define IDS_D3LAUNCHDLG_DSETUP_ERR_TITLE 164 +#define IDD_MOTD_DIALOG 165 +#define IDS_GLSETUP_ERROR 165 +#define IDD_PROPPAGE_DIRECTX 166 +#define IDS_LANG_ENGLISH 166 +#define IDB_PALETTE_BITMAP 167 +#define IDS_LANG_FRENCH 167 +#define IDS_LANG_GERMAN 168 +#define IDS_LANG_ITALIAN 169 +#define IDS_LANG_SPANISH 170 +#define IDS_D3LAUNCH_OEMV3_DLGTITLE 171 +#define IDS_D3LAUNCH_OEMA2_DLGTITLE 172 +#define IDS_D3LAUNCH_OEMKM_DLGTITLE 173 +#define IDS_D3LAUNCHDLG_UPDPRMT_MSG 174 +#define IDS_D3LAUNCHDLG_UPDPRMT_TITLE 175 +#define IDS_D3LAUNCH_OEM_DLGTITLE 176 +#define IDS_D3LAUNCH_DEMO2_DLGTITLE 177 +#define IDS_OPENGL_WARNING_MSG 178 +#define IDS_OPENGL_WARNING_TITLE 179 +#define IDS_NOTGLIDE_TITLE 180 +#define IDS_NOTGLIDE_MSG 181 +#define IDS_PROFANITY_MSG 182 +#define IDS_PROFANITY_TITLE 183 +#define IDS_GLSETUP_EXPIRED_MSG 184 +#define IDS_FINDFAST_MSG 185 +#define IDS_FINDFAST_TITLE 186 +#define IDS_OK 187 +#define IDS_CANCEL 188 +#define IDS_HELP 189 +#define IDD_MSG_DLG 205 +#define IDD_VIDEODETECT_DLG 206 +#define IDD_DRIVERS_DIALOG 215 +#define IDD_GLSETUP_DIALOG 216 +#define IDD_FINDFASTDLG 218 +#define IDC_BTN_QUIT 1001 +#define IDC_PROGRESS1 1001 +#define IDC_BTN_SETUP 1002 +#define IDC_LIST1 1002 +#define IDC_BTN_README 1003 +#define IDC_BTN_WEBPAGE 1004 +#define IDC_BTN_DETECT 1005 +#define IDC_BTN_CALIBRATE 1006 +#define IDC_JOYSTICK_LIST 1008 +#define IDC_FF_ENABLED 1009 +#define IDC_FF_HIT_EFFECT 1010 +#define IDC_VIDEOCARD_LIST 1011 +#define IDC_VIDEOCARD_DETECT 1012 +#define IDC_BTN_PLAY 1013 +#define IDC_AUDIO_LIST 1014 +#define IDC_BTN_AUDIO_DETECT 1015 +#define IDC_SPEED_LIST 1016 +#define IDC_BTN_UPDATE 1017 +#define IDC_BTN_SPEED_DETECT 1018 +#define IDC_USERMSG 1018 +#define IDC_CONNECT_TYPE_GROUP 1019 +#define IDC_CONNECT_SPEED_GROUP 1020 +#define IDC_BTN_LIGHT 1021 +#define IDC_CPU_TYPE 1024 +#define IDC_US_KEYBOARD 1024 +#define IDC_VRAM_SPEED 1025 +#define IDC_FRENCH_KEYBOARD 1025 +#define IDC_TOTAL_RAM 1026 +#define IDC_DX_VERSION 1026 +#define IDC_GERMAN_KEYBOARD 1026 +#define IDC_RAM_SPEED 1027 +#define IDC_GET_DX 1027 +#define IDC_WND_MSG_MAIN 1027 +#define IDC_CPU_SPEED 1028 +#define IDC_MSG1 1028 +#define IDC_WND_MSG_STATUS 1028 +#define IDC_DX_STATUS 1028 +#define IDC_3D_GRAPHICS_ACCELERATOR 1029 +#define IDC_MSG2 1029 +#define IDC_SITE_LIST 1029 +#define IDC_MSG3 1030 +#define IDC_MOTD_EDIT 1030 +#define IDC_YOUR_VERSION_EDIT 1032 +#define IDC_LATEST_VERSION_EDIT 1033 +#define IDC_MIXER_SOFTWARE 1034 +#define IDC_NONE 1035 +#define IDC_MIXER_DS8BIT 1035 +#define IDC_DIALUP 1036 +#define IDC_STATUSBAR 1036 +#define IDC_MIXER_DS16BIT 1036 +#define IDC_LAN 1037 +#define IDC_MIXER_DS3D 1037 +#define IDC_SLOW_CONNECTION 1038 +#define IDC_33K_CONNECTION 1038 +#define IDC_MIXER_AUREAL 1038 +#define IDC_56K_CONNECTION 1039 +#define IDC_BTN_PXO 1039 +#define IDC_CABLE_CONNECTION 1040 +#define IDC_BTN_UNINSTALL 1040 +#define IDC_BTN_DIRECTX 1041 +#define IDC_NO_CONNECTION 1043 +#define IDC_28K_CONNECTION 1043 +#define IDC_ANIM_BUTTON 1043 +#define IDC_FAST_CONNECTION 1044 +#define IDC_BTN_CANCEL 1044 +#define IDC_SINGLE_ISDN_CONNECTION 1045 +#define IDC_PRIMARY_JOYSTICK_TEXT 1045 +#define IDC_SCANNING_TEXT 1046 +#define IDC_WAIT_TEXT 1047 +#define IDC_DIRECT3D_CHECK 1049 +#define IDC_GLIDE_CHECK 1050 +#define IDC_OPENGL_CHECK 1051 +#define IDC_COMMANDLINE_EDIT 1052 +#define IDC_LAUNCHER_SND_CHECK 1053 +#define IDC_CUSTOM1 1057 +#define IDC_LANGUAGE_COMBO 1058 +#define IDC_DIRECTX_BUTTON 1059 +#define IDC_GLSETUP_BUTTON 1060 +#define IDC_INSTALL_BUTTON 1063 +#define IDC_VISIT_BUTTON 1064 +#define IDC_INFO_STATIC 1065 +#define IDC_INFO2_STATIC 1066 +#define IDC_INFO3_STATIC 1067 +#define IDC_MIXER_EAX 1068 +#define IDC_CHFLIGHT_CHECK 1069 +#define IDC_MOUSEMAN_CHECK 1070 +#define IDC_FINDFASTCHKBOX 1071 +#define IDC_FINDFAST_CHECK 1072 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 219 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1073 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/FontEditor/Args.h b/FontEditor/Args.h new file mode 100644 index 00000000..03a60e19 --- /dev/null +++ b/FontEditor/Args.h @@ -0,0 +1,29 @@ +/* + * $Source: /home/kevin/cvsstuff/descent3/descent3/Main/FontEditor/Args.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: kevinb $ + * $Date: 2003-08-26 03:57:45 $ + * + * Args header transferred from D3. + * + * $Log: not supported by cvs2svn $ + * + * 2 5/10/99 12:24p Samir + * added comment header + * + */ + +#ifndef ARGS_H +#define ARGS_H + +#define MAX_ARGS 15 +#define MAX_CHARS_PER_ARG 100 + +extern char GameArgs[MAX_ARGS][MAX_CHARS_PER_ARG]; + +// Gathers all arguments +void GatherArgs (char *str); + +// Returns index of argument sought, or 0 if not found +int FindArg (char *which); +#endif \ No newline at end of file diff --git a/FontEditor/FontCreate.cpp b/FontEditor/FontCreate.cpp new file mode 100644 index 00000000..910ca775 --- /dev/null +++ b/FontEditor/FontCreate.cpp @@ -0,0 +1,607 @@ +/* + * $Source: /home/kevin/cvsstuff/descent3/descent3/Main/FontEditor/FontCreate.cpp,v $ + * $Revision: 1.1.1.1 $ + * $Author: kevinb $ + * $Date: 2003-08-26 03:57:45 $ + * + * Font Creation + * + * $Log: not supported by cvs2svn $ + * + * 3 11/16/99 3:18p Samir + * updated fonteditor to include tracking. + * + * 2 4/24/99 5:43p Samir + * incremental checkin + * + * 1 4/17/99 4:04p Samir + * new font creator. + * + */ + + +#include "FontEditor.h" +#include "pstypes.h" +#include "pserror.h" +#include "bitmap.h" +#include "renderer.h" +#include "grtext.h" +#include "pstring.h" +#include "ddio.h" +#include "mem.h" + +#include +#include +#include + +// Font File stuff + +typedef FILE* FONTFILE; + +#define BITS_TO_BYTES(x) (((x)+7)>>3) + +inline int WRITE_FONT_INT(FONTFILE ffile, int i) { + return fwrite(&i, sizeof(i), 1, (FILE *)ffile); +} + +inline int WRITE_FONT_SHORT(FONTFILE ffile, short s) { + return fwrite(&s, sizeof(s), 1, (FILE *)ffile); +} + +inline int WRITE_FONT_BYTE(FONTFILE ffile, ubyte c) { + return fwrite(&c, sizeof(c), 1, (FILE *)ffile); +} + +inline int WRITE_FONT_DATA(FONTFILE ffile, void *buf, int size, int nelem) +{ + int i; + i = (int)fwrite(buf, size, nelem, (FILE *)ffile); + + ASSERT(i == nelem); + + return i; +} + +inline FONTFILE OPEN_FONT(char *filename) { + FONTFILE fp; + + fp = (FONTFILE)fopen(filename, "wb"); + if (!fp) return NULL; + + return fp; +} + +inline void CLOSE_FONT(FONTFILE ffile) { + fclose((FILE *)ffile); +} + + +void message_box(const char *fmt, ...) +{ +#define FIXED_MSGBOX_WIDTH (512) +#define FIXED_MSGBOX_HEIGHT (128) + + va_list arglist; + char buf[512]; + int len; + + va_start(arglist,fmt); + len = Pvsprintf(buf,512,fmt,arglist); + va_end(arglist); + if (len < 0) return; + + while(1) + { + int key; + int l = (FIXED_SCREEN_WIDTH-FIXED_MSGBOX_WIDTH)/2; + int t = (FIXED_SCREEN_HEIGHT-FIXED_MSGBOX_HEIGHT)/2; + int r = l+FIXED_MSGBOX_WIDTH; + int b = t+FIXED_MSGBOX_HEIGHT; + + FontDoIO(); + key = ddio_KeyInKey(); + if (key == KEY_ENTER || key == KEY_ESC) { + break; + } + + rend_StartFrame(0,0,FIXED_SCREEN_WIDTH,FIXED_SCREEN_HEIGHT,0); + grtext_SetParameters(0,0,FIXED_SCREEN_WIDTH,FIXED_SCREEN_HEIGHT); + grtext_SetFont(System_font_handle); + grtext_SetColor(GR_WHITE); + + rend_ClearScreen(GR_BLACK); + rend_SetFlatColor(GR_WHITE); + rend_DrawLine(l,t,r,t); + rend_DrawLine(r,t,r,b); + rend_DrawLine(l,b,r,b); + rend_DrawLine(l,t,l,b); + + grtext_CenteredPrintf(0,t+30, buf); + grtext_CenteredPrintf(0,b-30, "Press ENTER or ESC"); + grtext_Flush(); + rend_EndFrame(); + rend_Flip(); + } +} + + + +////////////////////////////////////////////////////////////////////////////////////// +#define COLOR_FONT 1 +#define MONOCHROME_FONT 2 +#define MAX_FONT_CHARS 256 + + + +static bool m_FontProp; +static ubyte m_CharWidths[MAX_FONT_CHARS]; +static short m_CharHeight; +static short m_CharMaxWidth; +static ushort *m_FontBmData; +static ushort *m_DataBuffer, *m_DataPtr; +static int m_FontType; +static int m_FontBmW, m_FontBmH; +static ushort m_FgColor, m_BgColor, m_BoxColor; + +#define PIX(_x,_y) m_FontBmData[(_x) + (_y) * m_FontBmW] + + +int read_font_char(int cur_char, int& bmx, int& bmy) +{ + int w,h,x,y; + bool box_edge = false; + + mprintf((0," %d-(%d,%d)",cur_char,bmx,bmy)); + + while (PIX(bmx+1,bmy+1) == m_BoxColor) + bmx++; //deal with double-thick vertical lines + + for (w=0;PIX(bmx+1+w,bmy+1)!=m_BoxColor;w++) + { + if (PIX(bmx+1+w,bmy)!=m_BoxColor) { + if (box_edge) { + message_box("Read probable premature eol at (%d,%d).\n", bmx+1+w, bmy); + w--; + return 2; + } + else { + message_box("Suspected error at pixel coordindates %d,%d (char %d)",bmx+1+w,bmy, cur_char); + return 0; + } + } + else { + box_edge = true; + } + } + + box_edge = false; + + for (h=0;PIX(bmx+1,bmy+1+h)!=m_BoxColor;h++) + { + if (PIX(bmx,bmy+1+h)!=m_BoxColor) { + if (box_edge) { + message_box("Read probable premature end of row at (%d,%d) (pix=%04x,box=%04x).\n", bmx, bmy+1+h, PIX(bmx,bmy+1+h), m_BoxColor); + h--; + return 2; + } + else { + message_box("Suspected error at pixel coordindates %d,%d (char %d)",bmx,bmy+1+h, cur_char); + return 0; + } + } + else { + box_edge = true; + } + } + + if (w==0 || h==0) { + message_box("Character %d has width of %d and height of %d",cur_char,w,h); + return 0; + } + if (w > 255 || w< 0) { + message_box("Character %d has bad width %d (maximum=255)", cur_char, w); + return 0; + } + + m_CharWidths[cur_char] = w; + + if (m_CharMaxWidth !=0 && w != m_CharMaxWidth) + m_FontProp = true; + + if (w > m_CharMaxWidth) m_CharMaxWidth = w; + + if (m_CharHeight == 0) + m_CharHeight = h; + else if (m_CharHeight != h) { + message_box("Char %d is wrong height (height = %d, correct height = %d)",cur_char,h,m_CharHeight); + return 0; + } + + for (y=0;ywidth = m_CharMaxWidth; + ft->height = m_CharHeight; + ft->flags = (m_FontProp?FT_PROPORTIONAL:0) + ((m_FontType==COLOR_FONT)?FT_COLOR:0); + ft->baseline = m_CharHeight; + ft->min_ascii = 0; + ft->max_ascii = cur_char-1; + ft->raw_data = (ubyte *)m_DataBuffer; + ft->char_data = NULL; + ft->char_widths = m_CharWidths; + ft->kern_data= NULL; + + ft->flags |= FT_FMT4444; + + return true; +} + + + +////////////////////////////////////////////////////////////////////////////////////////// +// Font file format. +// +// id=0xfeedbaba +// maximum width +// maximum height +// font flags +// baseline value (bashed brightness value) +// min and max ascii +// name +// for proportional fonts, store all widths +// no kerning. +// store font data. + + +void FontCreate(const char *fnt_file_source, const char *fnt_file_dest, int min_ascii) +{ +// import font + FONTFILE ffile; + tFontFileInfo ft; + int bm_handle; + char fontname[32]; + + strcpy(fontname, "d3font"); + + bm_handle = bm_AllocLoadFileBitmap(fnt_file_source, 0, BITMAP_FORMAT_4444); + if (bm_handle < 0) { + Error("Couldn't open %s for extraction.", fnt_file_source); + } + +// Get MinAscii and other needed info before extracting font. + if (!extract_font(bm_handle, &ft)) { + Error("Unable to generate font from %s.", fnt_file_source); + return; + } + +/////////////////////////////////////////////////////////////////////////////// +// Adjust font record for file write. + int num_char; + + ft.kern_data= NULL; + ft.min_ascii = min_ascii; + ft.max_ascii = ft.min_ascii + ft.max_ascii; + +// add newstyle variables here. + ft.flags |= FT_FFI2; + ft.ffi2.tracking = 0; + +// write to file + mprintf((0, "Saving font data...")); + ffile = OPEN_FONT((char *)fnt_file_dest); + if (!ffile) { + Error("Unable to save font %s.", fnt_file_dest); + } + +// Write file id. + WRITE_FONT_INT(ffile, 0xfeedbaba); + +// Write Header + ft.baseline = 0; + + WRITE_FONT_SHORT(ffile, ft.width); + WRITE_FONT_SHORT(ffile, ft.height); + WRITE_FONT_SHORT(ffile, ft.flags); + WRITE_FONT_SHORT(ffile, ft.baseline); + WRITE_FONT_BYTE(ffile, ft.min_ascii); + WRITE_FONT_BYTE(ffile, ft.max_ascii); + WRITE_FONT_DATA(ffile, fontname, 32, 1); + + WRITE_FONT_SHORT(ffile, (short)ft.ffi2.tracking); + WRITE_FONT_DATA(ffile, ft.ffi2.reserved, sizeof(ft.ffi2.reserved),1); + + num_char = (int)(ft.max_ascii - ft.min_ascii + 1); + +// Write widths now if necessary.(FT_PROPORTIONAL) + if (ft.flags & FT_PROPORTIONAL) { + for (int i = 0; i < num_char; i++) + WRITE_FONT_SHORT(ffile, ft.char_widths[i]); + } + + if (ft.flags & FT_COLOR) { + WRITE_FONT_INT(ffile, (int)(m_DataPtr-m_DataBuffer)*sizeof(ushort)); + WRITE_FONT_DATA(ffile, (ubyte *)m_DataBuffer, (m_DataPtr-m_DataBuffer)*sizeof(ushort), 1); + } + else { + // bitpack for mono font storage:: 16bpp -> 8 bits/1 byte + int i,x,y,w,cnt=0; + ushort *p = m_DataBuffer; + ubyte *bits; + + bits = (ubyte *)mem_malloc(256 * MAX_FONT_CHARS); + + for (i = 0; i < num_char; i++) + { + for (y = 0; y < ft.height; y++) + { + ubyte mask, datum; + + w = (ft.flags & FT_PROPORTIONAL) ? ft.char_widths[i] : ft.width; + + ASSERT(w <= 48); // Max width size shall be 32 pixels + + mask = 0x80; datum = 0; + + for (x = 0; x < w; x++) + { + if (mask == 0) { + bits[cnt++] = datum; + datum = 0; + mask = 0x80; + } + if (*p++ != 0x07e0) datum |= mask; + mask >>= 1; + } + + bits[cnt++] = datum; + } + } + + WRITE_FONT_INT(ffile, cnt); + WRITE_FONT_DATA(ffile, bits, cnt, 1); + mem_free(bits); + } + +// We should add kerning support here. + +// Close font. + CLOSE_FONT(ffile); + + delete[] m_DataBuffer; // allocated in extract_font! + bm_FreeBitmap(bm_handle); + + int new_font_handle = grfont_Load((char*)fnt_file_dest); + if (new_font_handle < 0) { + message_box("New font failed to load!"); + } + + +// print out stats. + while (1) + { + int x,y,i; + FontDoIO(); + + if (ddio_KeyInKey() == KEY_ENTER) { + break; + } + + rend_StartFrame(0,0,FIXED_SCREEN_WIDTH, FIXED_SCREEN_HEIGHT); + grtext_SetParameters(0,0,FIXED_SCREEN_WIDTH,FIXED_SCREEN_HEIGHT); + grtext_SetFont(System_font_handle); + grtext_SetColor(GR_WHITE); + rend_ClearScreen(GR_BLACK); + + grtext_Printf(0,12, "Created font:\2\65 %s", fnt_file_dest); + grtext_Printf(0,28, "Type:\2\65 %s, %s", (ft.flags & FT_COLOR) ? "COLOR" : "MONO", (ft.flags & FT_PROPORTIONAL) ? "PROPORTIONAL" : "FIXED WIDTH"); + grtext_Printf(0,40, "Ascii:\2\65 %d to %d", ft.min_ascii,ft.max_ascii); + grtext_Printf(0,52, "Maxwidth:\2\65 %d", ft.width); + grtext_Printf(0,64, "Maxheight:\2\65 %d", ft.height); + + grtext_Printf(0,FIXED_SCREEN_HEIGHT-20, "Press ENTER to quit."); + + // spew new font. + x=10; y = 120; + grtext_SetFont(new_font_handle); + + for (i = ft.min_ascii; i <= ft.max_ascii; i++) + { + char str[2]; + str[0] = i; + str[1] = 0; + + if ((x+grfont_GetCharWidth(new_font_handle, i)) > FIXED_SCREEN_WIDTH) { + x = 10; + y += grfont_GetHeight(new_font_handle)+1; + } + + grtext_Puts(x,y,str); + x+= grfont_GetCharWidth(new_font_handle, i)+1; + } + + grtext_Flush(); + rend_EndFrame(); + rend_Flip(); + } + + grfont_Free(new_font_handle); +} + + +void FontView(const char *fnt_file_name) +{ + tFontTemplate ft; + int new_font_handle; + + new_font_handle = grfont_Load((char *)fnt_file_name); + if (new_font_handle < 0) { + Error("Couldn't load font %s.", fnt_file_name); + } + grfont_LoadTemplate((char *)fnt_file_name, &ft); + + ddio_KeyFlush(); +// print out stats. + while (1) + { + int x,y,i; + + FontDoIO(); + + if (ddio_KeyInKey() == KEY_ENTER) { + break; + } + + rend_StartFrame(0,0,FIXED_SCREEN_WIDTH, FIXED_SCREEN_HEIGHT); + grtext_SetParameters(0,0,FIXED_SCREEN_WIDTH,FIXED_SCREEN_HEIGHT); + grtext_SetFont(System_font_handle); + grtext_SetColor(GR_WHITE); + rend_ClearScreen(GR_BLACK); + + grtext_Printf(0,12, "Font:\2\65 %s", fnt_file_name); + grtext_Printf(0,28, "Type:\2\65 %s, %s, %s", (ft.monochromatic ? "MONO" : "COLOR"), (ft.proportional ? "PROPORTIONAL" : "FIXED WIDTH"), + (ft.newstyle ? "4444" : "1555")); + grtext_Printf(0,40, "Ascii:\2\65 %d to %d", ft.min_ascii,ft.max_ascii); + grtext_Printf(0,52, "Maxwidth:\2\65 %d", ft.ch_maxwidth); + grtext_Printf(0,64, "Maxheight:\2\65 %d", ft.ch_height); + + if (ft.ffi2) { + grtext_Printf(0,76, "Tracking:\2\65 %d", (int)ft.ch_tracking); + } + + + grtext_Printf(0,FIXED_SCREEN_HEIGHT-20, "Press ENTER to quit."); + + // spew new font. + x=10; y = 120; + grtext_SetFont(new_font_handle); + + for (i = ft.min_ascii; i <= ft.max_ascii; i++) + { + char str[2]; + str[0] = i; + str[1] = 0; + + if ((x+grfont_GetCharWidth(new_font_handle, i)) > FIXED_SCREEN_WIDTH) { + x = 10; + y += grfont_GetHeight(new_font_handle)+1; + } + + grtext_Puts(x,y,str); + x+= grfont_GetCharWidth(new_font_handle, i)+1; + } + + grtext_Flush(); + + rend_EndFrame(); + rend_Flip(); + + } + + grfont_Free(new_font_handle); +} diff --git a/FontEditor/FontEditor.cpp b/FontEditor/FontEditor.cpp new file mode 100644 index 00000000..9c7d83df --- /dev/null +++ b/FontEditor/FontEditor.cpp @@ -0,0 +1,211 @@ +/* + * $Source: /home/kevin/cvsstuff/descent3/descent3/Main/FontEditor/FontEditor.cpp,v $ + * $Revision: 1.1.1.1 $ + * $Author: kevinb $ + * $Date: 2003-08-26 03:57:45 $ + * + * Font Editor main body + * + * $Log: not supported by cvs2svn $ + * + * 5 11/16/99 3:18p Samir + * updated fonteditor to include tracking. + * + * 4 5/19/99 8:48p Samir + * added kerning dump utilitiy. + * + * 3 4/24/99 5:43p Samir + * incremental checkin + * + * 2 4/17/99 4:05p Samir + * complete font editor. + * + */ + +// FontEditor.cpp : Defines the entry point for the application. +// + +#include "stdafx.h" + +#include "FontEditor.h" +#include "application.h" +#include "pserror.h" +#include "ddio.h" +#include "renderer.h" +#include "grtext.h" +#include "bitmap.h" +#include "mem.h" +#include "args.h" +#include "cfile.h" + +#include + +#define APPNAME "Font Kerner" + +renderer_type Preferred_renderer = RENDERER_OPENGL; + +void InitSystems(oeApplication *app, bool debug, bool mono, renderer_type renderer); +void InitIO(oeApplication *app); +void InitRenderer(oeApplication *app, renderer_type renderer); +extern void FontKern(const char *fnt_file_name); +extern void FontCreate(const char *fnt_file_source, const char *fnt_file_dest, int min_ascii, int max_ascii, int type); + +class oeApplication *FontEditor = NULL; +int System_font_handle = -1; + +class appFontKerner: public oeWin32Application +{ + bool shutdown; + +public: + appFontKerner(HInstance hinst): oeWin32Application(APPNAME, OEAPP_FULLSCREEN, hinst) { shutdown = false; }; + +// returns 0 if we pass to default window handler. + virtual int WndProc( HWnd hwnd, unsigned msg, unsigned wParam, long lParam) + { + switch (msg) + { + case WM_ACTIVATEAPP: + if (wParam == (unsigned)(FALSE) && !shutdown && FontEditor) { + shutdown = true; + rend_Close(); + ddio_Close(); + ShowWindow((HWND)hwnd, SW_MINIMIZE); + this->deactivate(); + } + else if (wParam == (unsigned)(TRUE) && shutdown && FontEditor) { + this->activate(); + ShowWindow((HWND)hwnd, SW_MAXIMIZE); + InitIO(this); + InitRenderer(this, Preferred_renderer); + shutdown = false; + } + break; + + } + + return oeWin32Application::WndProc(hwnd, msg, wParam, lParam); + }; +}; + + + + +int APIENTRY WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + appFontKerner fontkern((HInstance)hInstance); + int i; + + fontkern.init(); + + GatherArgs(lpCmdLine); + + i = FindArg("-glide"); + if (i) Preferred_renderer = RENDERER_GLIDE; + + i = FindArg("-create"); + if (i) { + int min_ascii = atoi(GameArgs[i+3]); + InitSystems(&fontkern, false, false, Preferred_renderer); + FontCreate(GameArgs[i+1], GameArgs[i+2], min_ascii); + return 0; + } + + i = FindArg("-kern"); + if (i) { + InitSystems(&fontkern, false, false, Preferred_renderer); + FontKern(GameArgs[i+1]); + return 0; + } + + i = FindArg("-view"); + if (i) { + InitSystems(&fontkern, false, false, Preferred_renderer); + FontView(GameArgs[i+1]); + return 0; + } + + i = FindArg("-kerndump"); + if (i) { + error_Init(false, false, APPNAME); + SetMessageBoxTitle(APPNAME " Message"); + mem_Init(); + FontEditor = &fontkern; + InitIO(&fontkern); + grfont_Reset(); + grtext_Init(); + FontKernDump(GameArgs[i+1]); + return 0; + } + + MessageBox(NULL, "Need to specify a font to edit.", "Error",MB_OK); + + return 0; +} + + +void InitSystems(oeApplication *app, bool debug, bool mono, renderer_type renderer) +{ + error_Init(debug, mono, APPNAME); + SetMessageBoxTitle(APPNAME " Message"); + + mem_Init(); InitIO(app); + + cf_OpenLibrary("fonteditor.hog"); + bm_InitBitmaps(); + grfont_Reset(); + grtext_Init(); + InitRenderer(app, renderer); + + System_font_handle = grfont_Load("system.fnt"); + if (System_font_handle < 0) { + Error("Failed to load system font."); + } + + FontEditor = app; +} + + +void InitIO(oeApplication *app) +{ + char path[1024]; + + ddio_init_info ddio_init_data; + + ddio_init_data.obj = app; + ddio_init_data.use_lo_res_time = true; + ddio_init_data.key_emulation = true; + ddio_init_data.joy_emulation = true; + ddio_Init(&ddio_init_data); + + GetCurrentDirectory(sizeof(path), path); + cf_SetSearchPath(path,NULL); +} + + +void InitRenderer(oeApplication *app, renderer_type renderer) +{ + renderer_preferred_state req_renderer_state; + + req_renderer_state.width = FIXED_SCREEN_WIDTH; + req_renderer_state.height = FIXED_SCREEN_HEIGHT; + req_renderer_state.bit_depth = 16; + req_renderer_state.gamma = 1.6f; + req_renderer_state.vsync_on = true; + req_renderer_state.filtering = true; + req_renderer_state.mipping = false; + + if (!rend_Init(renderer, app, &req_renderer_state)) { + Error("Failed to initialize renderer."); + } +} + + +void FontDoIO() +{ + FontEditor->defer(); + ddio_Frame(); +} diff --git a/FontEditor/FontEditor.h b/FontEditor/FontEditor.h new file mode 100644 index 00000000..4710af53 --- /dev/null +++ b/FontEditor/FontEditor.h @@ -0,0 +1,26 @@ +/* + * $Source: /home/kevin/cvsstuff/descent3/descent3/Main/FontEditor/FontEditor.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: kevinb $ + * $Date: 2003-08-26 03:57:45 $ + * + * Font Editor + * + * $Log: not supported by cvs2svn $ + * + * 2 5/19/99 8:48p Samir + * added kerning dump utilitiy. + * + * 1 4/17/99 4:04p Samir + * standard header. + * + */ + +extern void FontDoIO(); +extern void FontKern(const char *fnt_file_name); +extern void FontKernDump(const char *fnt_file_name); +extern void FontView(const char *fnt_file_name); +extern void FontCreate(const char *fnt_file_source, const char *fnt_file_dest, int min_ascii); + +extern int System_font_handle; + diff --git a/FontEditor/FontKern.cpp b/FontEditor/FontKern.cpp new file mode 100644 index 00000000..a8decbe9 --- /dev/null +++ b/FontEditor/FontKern.cpp @@ -0,0 +1,503 @@ +/* + * $Source: /home/kevin/cvsstuff/descent3/descent3/Main/FontEditor/FontKern.cpp,v $ + * $Revision: 1.1.1.1 $ + * $Author: kevinb $ + * $Date: 2003-08-26 03:57:45 $ + * + * Kerning + * + * $Log: not supported by cvs2svn $ + * + * 4 11/16/99 3:18p Samir + * updated fonteditor to include tracking. + * + * 3 5/19/99 8:48p Samir + * added kerning dump utilitiy. + * + * 2 4/17/99 4:05p Samir + * complete font editor. + * + */ + +#include "FontEditor.h" +#include "pserror.h" +#include "renderer.h" +#include "ddio.h" +#include "grtext.h" +#include "bitmap.h" +#include "mem.h" + +#include +#include + + +chunked_bitmap Editor_bkg; +tFontTemplate Font_template; + +char *SampleText = "This is some sample text that is here to\n" \ +"Show you how the antialiasing will\n" \ +"look over different color backgrounds\n" \ +"KERN PAIRS: VaWaVeWeVAV-LyT.T,TyTvTcYe\n"; + + +// this function determines if a kerning pair exists in the current font template +// if there is no kerning structure, add it. if no kerning in font, add it to the template +#define KERNINFO_PAIR_SIZE 3 + +int fonttool_get_kerning( int c1, int c2, int *pairnum=NULL); + +int fonttool_get_kerning( int c1, int c2, int *pairnum) +{ + int i; + ubyte *kern_data; + + + kern_data= Font_template.kern_data; + if (kern_data) { + i=0; + while (kern_data[i] != 255) + { + if (kern_data[i] == (ubyte)c1 && kern_data[i+1] == (ubyte)c2) { + if (pairnum) *pairnum = i/3; + return (int)((sbyte)kern_data[i+2]); + } + i+=KERNINFO_PAIR_SIZE; + } + } + + return 0; +} + + +void fonttool_set_kerning( int c1, int c2, int dist ) +{ + int i,j; + ubyte *kern_data; + + if (c1 == 255 || c2 == 255) { + mprintf((0, "seting illegal kerning of 255!\n")); + return; + } + + kern_data= Font_template.kern_data; + + if (!kern_data) { + // create a one entry kern table. + kern_data = (ubyte *)mem_malloc(KERNINFO_PAIR_SIZE*2); + kern_data[0] = (ubyte)c1; + kern_data[1] = (ubyte)c2; + kern_data[2] = (sbyte)dist; + kern_data[3] = 255; + kern_data[4] = 255; + kern_data[5] = 0; + Font_template.kern_data = kern_data; + mprintf((0, "adding first kerning pair %d,%d\n", c1,c2)); + return; + } + +// check for match in current list. + i=0; + while (kern_data[i] != 255) + { + if (kern_data[i] == (ubyte)c1 && kern_data[i+1] == (ubyte)c2) { + kern_data[i+2] = (sbyte)dist; + if (dist == 0) { + // remove this kerning pair. + j = i; + do + { + kern_data[j] = kern_data[j+3]; + kern_data[j+1] = kern_data[j+4]; + kern_data[j+2] = kern_data[j+5]; + j+= KERNINFO_PAIR_SIZE; + } + while (kern_data[j] != 255); + if (i == 0) { + // last pair, deallocate kern_data and end. + mprintf((0, "removing last kerning pair\n")); + mem_free(kern_data); + kern_data = NULL; + } + else { + mprintf((0, "removing kerning pair %d,%d\n", c1,c2)); + } + } + Font_template.kern_data = kern_data; + return; + } + i+=KERNINFO_PAIR_SIZE; + } + +// new entry. + ubyte *new_kern_data; + int n_pairs = i/KERNINFO_PAIR_SIZE; + + new_kern_data = (ubyte *)mem_malloc((n_pairs+2)*sizeof(ubyte)*KERNINFO_PAIR_SIZE); + for (i = 0; i < n_pairs; i++) + { + new_kern_data[i*KERNINFO_PAIR_SIZE] = kern_data[i*3]; + new_kern_data[i*KERNINFO_PAIR_SIZE+1] = kern_data[i*3+1]; + new_kern_data[i*KERNINFO_PAIR_SIZE+2] = kern_data[i*3+2]; + } + new_kern_data[i*KERNINFO_PAIR_SIZE] = (ubyte)c1; + new_kern_data[i*KERNINFO_PAIR_SIZE+1] = (ubyte)c2; + new_kern_data[i*KERNINFO_PAIR_SIZE+2] = (sbyte)dist; + i++; + new_kern_data[i*KERNINFO_PAIR_SIZE] = 255; + new_kern_data[i*KERNINFO_PAIR_SIZE+1] = 255; + new_kern_data[i*KERNINFO_PAIR_SIZE+2] = 0; + + mem_free(kern_data); + + Font_template.kern_data = new_kern_data; + + mprintf((0, "adding first kerning pair %d,%d (total=%d)\n", c1,c2, n_pairs+1)); +} + + +void fonttool_remove_kerning() +{ + if (Font_template.kern_data) { + mem_free(Font_template.kern_data); + Font_template.kern_data = NULL; + } +} + + +///////////////////////////////////////////////////////////////////////////// + +void FontKern(const char *fnt_file_name) +{ + int bm_handle; + int font_handle; + int c1 = 'b', c2 = 'u', d; + int last_good_pair, current_pair; + int first_item = 0; + int current_item = 0; + int num_items_displayed = 1; + bool done = false; + short text_alpha=255; + int red_comp , green_comp, blue_comp; + ddgr_color text_color; + + red_comp = green_comp = blue_comp = 255; + + bm_handle = bm_AllocLoadFileBitmap("FontTool.ogf",0); + if (bm_handle <= BAD_BITMAP_HANDLE) { + Error("Error loading FontEditor art."); + } + if (!bm_CreateChunkedBitmap(bm_handle, &Editor_bkg)) { + Error("Error chunking FontEditor art."); + } + bm_FreeBitmap(bm_handle); + +// load font into memory. + font_handle = grfont_Load((char *)fnt_file_name); + if (font_handle < 0) { + Error("Error loading font %s", fnt_file_name); + } + if (!grfont_LoadTemplate((char *)fnt_file_name, &Font_template)) { + Error("Error loading font template %s", fnt_file_name); + } + + if (Font_template.ffi2 == false) { + Font_template.ffi2 = true; + Font_template.ch_tracking = 0; + } + + if (Font_template.kern_data) { + current_pair = 0; + } + else { + current_pair = -1; + } + + last_good_pair = current_pair; + + while(!done) + { + int key; + + FontDoIO(); + + key = ddio_KeyInKey(); + switch (key) + { + case KEY_ESC: + done = true; + break; + + case KEY_F5: + grfont_Free(font_handle); + grfont_FreeTemplate(&Font_template); + font_handle = grfont_Load((char *)fnt_file_name); + if (font_handle == -1) { + Error("Font failed reload test!"); + } + grfont_LoadTemplate((char *)fnt_file_name, &Font_template); + break; + + case KEY_MINUS: + if (Font_template.ch_tracking > -80) { + Font_template.ch_tracking--; + grfont_SetTracking(font_handle, Font_template.ch_tracking); + } + break; + + case KEY_EQUAL: + if (Font_template.ch_tracking < 80) { + Font_template.ch_tracking++; + grfont_SetTracking(font_handle, Font_template.ch_tracking); + } + break; + + case KEY_F10: + grfont_Free(font_handle); + if (!grfont_SetTemplate(fnt_file_name, &Font_template)) { + Error("Failed to save font correctly!"); + } + grfont_FreeTemplate(&Font_template); + font_handle = grfont_Load((char *)fnt_file_name); + if (font_handle == -1) { + Error("Font failed reload test on save!"); + } + grfont_LoadTemplate((char *)fnt_file_name, &Font_template); + mprintf((0, "font saved and reloaded correctly?\n")); + done = true; + break; + + case KEY_F6: + fonttool_remove_kerning(); + break; + + case KEY_COMMA: + text_alpha -= 16; + if (text_alpha < 0) text_alpha = 0; + break; + + case KEY_PERIOD: + text_alpha += 16; + if (text_alpha > 255) text_alpha = 255; + break; + + case KEY_PAD7: + c1++; + if (c1 > Font_template.max_ascii) c1 = Font_template.min_ascii; + break; + + case KEY_PAD9: + c2++; + if (c2 > Font_template.max_ascii) c2 = Font_template.min_ascii; + break; + + case KEY_PAD1: + c1--; + if (c1 < Font_template.min_ascii) c1 = Font_template.max_ascii; + break; + + case KEY_PAD3: + c2--; + if (c2 < Font_template.min_ascii) c2 = Font_template.max_ascii; + break; + + case KEY_PAD4: + d = fonttool_get_kerning(c1,c2); + fonttool_set_kerning(c1, c2, d-1); + grfont_SetKerning(font_handle, Font_template.kern_data); + break; + + case KEY_PAD5: + fonttool_set_kerning(c1,c2,0); + break; + + case KEY_PAD6: + d = fonttool_get_kerning(c1,c2); + fonttool_set_kerning(c1,c2,d+1); + grfont_SetKerning(font_handle, Font_template.kern_data); + break; + + case KEY_PAD2: + if ( current_pair < 0 ) { + current_pair = last_good_pair; + } + + if (current_pair >= 0) { + ubyte *kern_data = &Font_template.kern_data[current_pair*3]; + if (kern_data[3] != 255) { + current_pair++; + kern_data = &Font_template.kern_data[current_pair*3]; + } + c1 = kern_data[0]; + c2 = kern_data[1]; + } + break; + + case KEY_PAD8: + if ( current_pair < 0 ) { + current_pair = last_good_pair; + } + + if (current_pair >= 0) { + ubyte *kern_data = &Font_template.kern_data[current_pair*3]; + if (kern_data != Font_template.kern_data) { + // gosh, comparing pointers like this may not be the best method...this is shitty code... + current_pair--; + kern_data = &Font_template.kern_data[current_pair*3]; + } + c1 = kern_data[0]; + c2 = kern_data[1]; + } + break; + + case KEY_R: + red_comp = red_comp ? 0 : 255; + break; + case KEY_G: + green_comp = green_comp ? 0 : 255; + break; + case KEY_B: + blue_comp = blue_comp ? 0 : 255; + break; + } + + // draw. + text_color = GR_RGB(red_comp, green_comp, blue_comp); + + rend_StartFrame(0,0,FIXED_SCREEN_WIDTH,FIXED_SCREEN_HEIGHT,0); + grtext_SetParameters(0,0,FIXED_SCREEN_WIDTH,FIXED_SCREEN_HEIGHT); + grtext_SetFont(font_handle); + grtext_SetColor(text_color); + grtext_SetAlpha((ubyte)text_alpha); + + rend_ClearScreen(GR_BLACK); + rend_DrawChunkedBitmap(&Editor_bkg, 0, 0, 255); + + grtext_Printf(240,210,"%c (%d)", c1, c1); + grtext_Printf(340,210,"%c (%d)", c2, c2); + + grtext_CenteredPrintf(0, 240, "Ham%c%crger", c1, c2); + + grtext_CenteredPrintf(0, 270, "HAM%c%cRGER", c1, c2); + + grtext_CenteredPrintf(0, 300, "Offset: %d pixels", fonttool_get_kerning(c1, c2)); + grtext_CenteredPrintf(0, 320, "Tracking: %d pixels", (int)Font_template.ch_tracking); + { + int th; + th = grtext_GetTextHeight(SampleText); + + grtext_Printf(10,350,SampleText); + grtext_Printf(10,350+th+10, SampleText); + } + + // display kerned pairs. + int x = 5, y = 200, i, n, widest=0; + int n_pairs=0, stop; + int tmpp=-1; + char kerntext[16]; + + if (Font_template.kern_data) { + i=0; + while (Font_template.kern_data[i] != 255) + { + n_pairs++; + i+=KERNINFO_PAIR_SIZE; + } + } + + // update current pair values + if ( current_pair >= n_pairs ) { + current_pair = -1; + } + + fonttool_get_kerning(c1, c2, &tmpp ); + + if ( tmpp != -1 ) { + current_pair = tmpp; + } else { + if ( current_pair > -1 ) + last_good_pair = current_pair; + current_pair = -1; + } + if (current_pair > -1) { current_item = current_pair; } + if (current_item < 0) { current_item = 0; } + if (current_item >= n_pairs) { current_item = n_pairs-1; } + if (current_item < first_item) { first_item = current_item; } + if (current_item >= (first_item+num_items_displayed)) { first_item = current_item-num_items_displayed+1; } + if (n_pairs <= num_items_displayed) { first_item = 0; } + stop = first_item+num_items_displayed; + if (stop>n_pairs) stop = n_pairs; + + for (i=first_item,n=0; i widest) {widest = tw; } + y += th; + if (y > 330) { + y = 200; + x += widest+5; + if (x > 150) { + num_items_displayed = n; + break; + } + widest = 0; + } + } + if (i == stop) { num_items_displayed++; } + if (num_items_displayed < 1) {num_items_displayed = 1;} + if (num_items_displayed > n_pairs) { num_items_displayed = n_pairs; } + + + grtext_Flush(); + rend_EndFrame(); + rend_Flip(); + } + + grfont_FreeTemplate(&Font_template); + grfont_Free(font_handle); + bm_DestroyChunkedBitmap(&Editor_bkg); +} + + + +void FontKernDump(const char *fnt_file_name) +{ + if (!grfont_LoadTemplate((char *)fnt_file_name, &Font_template)) { + Error("Error loading font template %s", fnt_file_name); + } + + if (Font_template.kern_data) { + FILE *fp; + char filename[_MAX_PATH]; + + sprintf(filename, "%s.kern", fnt_file_name); + fp = fopen(filename, "wt"); + if (fp) { + ubyte *kern_data = Font_template.kern_data; + while (kern_data[0] != 255) + { + ubyte c1 = kern_data[0]; + ubyte c2 = kern_data[1]; + sbyte delta = (sbyte)kern_data[2]; + + fprintf(fp, "%c %c => %d spacing\n", c1,c2,(int)delta); + kern_data += 3; + } + fclose(fp); + } + } + + grfont_FreeTemplate(&Font_template); +} diff --git a/FontEditor/StdAfx.cpp b/FontEditor/StdAfx.cpp new file mode 100644 index 00000000..011c57c0 --- /dev/null +++ b/FontEditor/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// FontEditor.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/FontEditor/StdAfx.h b/FontEditor/StdAfx.h new file mode 100644 index 00000000..8baa7c7a --- /dev/null +++ b/FontEditor/StdAfx.h @@ -0,0 +1,23 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) +#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include + + +// TODO: reference additional headers your program requires here + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) diff --git a/FontEditor/args.cpp b/FontEditor/args.cpp new file mode 100644 index 00000000..d767c247 --- /dev/null +++ b/FontEditor/args.cpp @@ -0,0 +1,86 @@ +/* + * $Source: /home/kevin/cvsstuff/descent3/descent3/Main/FontEditor/args.cpp,v $ + * $Revision: 1.1.1.1 $ + * $Author: kevinb $ + * $Date: 2003-08-26 03:57:45 $ + * + * Transferred from Descent 3 + * + * $Log: not supported by cvs2svn $ + * + * 2 4/17/99 4:05p Samir + * complete font editor. + * + */ + +#include "args.h" +#include "mono.h" +#include + +static int TotalArgs=0; +char GameArgs[MAX_ARGS][MAX_CHARS_PER_ARG]; + +// Gathers all arguments +void GatherArgs (char *str) +{ + int i,t,curarg=1; + int len=strlen(str); + bool gotquote = false; + + for (t=0,i=0;i +* +* $Log: not supported by cvs2svn $ + * + * 33 10/21/99 9:28p Jeff + * B.A. Macintosh code merge + * + * 32 5/12/99 11:28a Jeff + * added sourcesafe comment block +* +* $NoKeywords: $ +*/ + + + +#ifndef __DMFC_APP_H_ +#define __DMFC_APP_H_ + +#include "osiris_share.h" +#include "d3events.h" + +//Setup and processing functions +void AnarchyGameInit(int teams); +void AnarchyGameClose(void); + +void OnKeypress(int key); +void OnHUDInterval(void); +void OnInterval(void); +void OnClientPlayerKilled(object *killer_obj,int victim_pnum); +void OnClientPlayerEntersGame(int player_num); +void OnClientLevelStart(void); +void OnClientLevelEnd(void); +void OnServerGameCreated(void); +void OnPLRInterval(void); +void OnPLRInit(void); +void OnSaveStatsToFile(void); +void OnLevelEndSaveStatsToFile(void); +void OnDisconnectSaveStatsToFile(void); +void OnPrintScores(int level); +extern IDMFC *DMFCBase; + + + +/************************************************************************************************* + *The following functions and declaration are needed to connect the DLL to the game. These must * + *stay here and must call the functions that are in them. You can not delete from here, but you * + *can add to it no problem * + ************************************************************************************************* +*/ +// These next two function prototypes MUST appear in the extern "C" block if called +// from a CPP file. +#ifdef __cplusplus +extern "C" +{ +#endif + DLLEXPORT void DLLFUNCCALL DLLGameInit (int *api_func,ubyte *all_ok,int num_teams_to_use); + DLLEXPORT void DLLFUNCCALL DLLGameCall (int eventnum,dllinfo *data); + DLLEXPORT void DLLFUNCCALL DLLGameClose (); + DLLEXPORT void DLLFUNCCALL DLLGetGameInfo (tDLLOptions *options); + DLLEXPORT int DLLFUNCCALL GetGOScriptID(char *name,ubyte isdoor); + DLLEXPORT void DLLFUNCCALLPTR CreateInstance(int id); + DLLEXPORT void DLLFUNCCALL DestroyInstance(int id,void *ptr); + DLLEXPORT short DLLFUNCCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data); + DLLEXPORT int DLLFUNCCALL SaveRestoreState( void *file_ptr, ubyte saving_state ); +#ifdef __cplusplus +} +#endif + +#ifdef MACINTOSH +#pragma export on +#endif + +// The main entry point where the game calls the dll +void DLLFUNCCALL DLLGameCall (int eventnum,dllinfo *data) +{ + if((eventnumGetLocalRole()!=LR_SERVER)){ + return; + } + + DMFCBase->TranslateEvent(eventnum,data); +} + + +// GetGOScriptID +// Purpose: +// Given the name of the object (from it's pagename), this function will search through it's +// list of General Object Scripts for a script with a matching name (to see if there is a script +// for that type/id of object within this DLL). If a matching scriptname is found, a UNIQUE ID +// is to be returned back to Descent 3. This ID will be used from here on out for all future +// interaction with the DLL. Since doors are not part of the generic object's, it's possible +// for a door to have the same name as a generic object (OBJ_POWERUP, OBJ_BUILDING, OBJ_CLUTTER +// or OBJ_ROBOT), therefore, a 1 is passed in for isdoor if the given object name refers to a +// door, else it is a 0. The return value is the unique identifier, else -1 if the script +// does not exist in the DLL. +int DLLFUNCCALL GetGOScriptID(char *name,ubyte isdoor) +{ + return -1; +} + +// CreateInstance +// Purpose: +// Given an ID from a call to GetGOScriptID(), this function will create a new instance for that +// particular script (by allocating and initializing memory, etc.). A pointer to this instance +// is to be returned back to Descent 3. This pointer will be passed around, along with the ID +// for CallInstanceEvent() and DestroyInstance(). Return NULL if there was an error. +void DLLFUNCCALLPTR CreateInstance(int id) +{ + return NULL; +} + +// DestroyInstance +// Purpose: +// Given an ID, and a pointer to a particular instance of a script, this function will delete and +// destruct all information associated with that script, so it will no longer exist. +void DLLFUNCCALL DestroyInstance(int id,void *ptr) +{ +} + +// CallInstanceEvent +// Purpose: +// Given an ID, a pointer to a script instance, an event and a pointer to the struct of +// information about the event, this function will translate who this event belongs to and +// passes the event to that instance of the script to be handled. Return a combination of +// CONTINUE_CHAIN and CONTINUE_DEFAULT, to give instructions on what to do based on the +// event. CONTINUE_CHAIN means to continue through the chain of scripts (custom script, level +// script, mission script, and finally default script). If CONTINUE_CHAIN is not specified, +// than the chain is broken and those scripts of lower priority will never get the event. Return +// CONTINUE_DEFAULT in order to tell D3 if you want process the normal action that is built into +// the game for that event. This only pertains to certain events. If the chain continues +// after this script, than the CONTINUE_DEFAULT setting will be overridden by lower priority +// scripts return value. +short DLLFUNCCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data) +{ + return CONTINUE_CHAIN|CONTINUE_DEFAULT; +} + +// SaveRestoreState +// Purpose: +// This function is called when Descent 3 is saving or restoring the game state. In this function +// you should save/restore any global data that you want preserved through load/save (which includes +// demos). You must be very careful with this function, corrupting the file (reading or writing too +// much or too little) may be hazardous to the game (possibly making it impossible to restore the +// state). It would be best to use version information to keep older versions of saved states still +// able to be used. IT IS VERY IMPORTANT WHEN SAVING THE STATE TO RETURN THE NUMBER OF _BYTES_ WROTE +// TO THE FILE. When restoring the data, the return value is ignored. saving_state is 1 when you should +// write data to the file_ptr, 0 when you should read in the data. +int DLLFUNCCALL SaveRestoreState( void *file_ptr, ubyte saving_state ) +{ + return 0; +} + +#ifdef MACINTOSH +#pragma export off +#endif + +#endif diff --git a/anarchy/Makefile b/anarchy/Makefile new file mode 100644 index 00000000..49fc25cb --- /dev/null +++ b/anarchy/Makefile @@ -0,0 +1,24 @@ +include ../../default.mak + +OBJS = anarchy.o +REFS = anarchy.cpp +LIBNAME = ../../netgames/anarchy.d3m + +CDLFLAGS = $(CFLAGS) -fPIC +LDLFLAGS = -shared -ldl + +all: depall $(OBJS) + gcc $(LDLFLAGS) -o $(LIBNAME) $(OBJS) /usr/lib/dmfc.so + +depall: + $(CC) -E -M $(CFLAGS) $(DEFINES) $(REFS) > .depend + +clean: + rm -f $(OBJS) *~ $(LIBNAME) core + +%.o: %.cpp + $(CC) $(CDLFLAGS) $(DEFINES) -c $< -o $@ + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/anarchy/anarchy.cpp b/anarchy/anarchy.cpp new file mode 100644 index 00000000..1969ebc3 --- /dev/null +++ b/anarchy/anarchy.cpp @@ -0,0 +1,1017 @@ +/* +* $Logfile: /DescentIII/Main/anarchy/anarchy.cpp $ +* $Revision: 1.1.1.1 $ +* $Date: 2003-08-26 03:56:37 $ +* $Author: kevinb $ +* +* +* +* $Log: not supported by cvs2svn $ + * + * 84 11/08/99 11:42p Jeff + * SourceSafe Test...ignore + * + * 83 10/21/99 9:27p Jeff + * B.A. Macintosh code merge + * + * 82 7/12/99 1:22p Jeff + * updated for new netflags + * + * 81 7/11/99 6:43p Jeff + * cleaner plr if the list is too long + * + * 80 5/23/99 3:04a Jason + * fixed bug with player rankings not being updated correctly + * + * 79 5/12/99 11:28a Jeff + * added sourcesafe comment block +* +* $NoKeywords: $ +*/ + + + +#include +#include +#include +#include "idmfc.h" +#include "Anarchy.h" +#include "anarchystr.h" +IDMFC *DMFCBase = NULL; +IDmfcStats *dstat = NULL; + +int SortedPlayers[MAX_PLAYER_RECORDS]; //sorted player nums +bool DisplayScoreScreen; +int Highlight_bmp = -1; + +#define AHD_NONE 0 +#define AHD_SCORE 1 +#define AHD_EFFICIENCY 2 +#define ACM_PLAYERCOLOR 0 +#define ACM_NORMAL 1 +ubyte Anarchy_hud_display = AHD_SCORE; +ubyte HUD_color_model = ACM_PLAYERCOLOR; +bool display_my_welcome = false; + +void DisplayHUDScores(struct tHUDItem *hitem); +void DisplayScores(void); +void DisplayWelcomeMessage(int player_num); +void SaveStatsToFile(char *filename); +void SwitchHUDColor(int i); + +/////////////////////////////////////////////// +//localization info +char **StringTable; +int StringTableSize = 0; +char *_ErrorString = "Missing String"; +char *GetString(int d){if( (d<0) || (d>=StringTableSize) ) return _ErrorString; else return StringTable[d];} +/////////////////////////////////////////////// + +void SwitchAnarchyScores(int i) +{ + if(i<0) + i = 0; + if(i>2) + i = 2; + + Anarchy_hud_display = i; + + switch(i){ + case AHD_NONE: + DLLAddHUDMessage(TXT_HUDD_NONE); + break; + case AHD_SCORE: + DLLAddHUDMessage(TXT_HUDD_SCORES); + break; + case AHD_EFFICIENCY: + DLLAddHUDMessage(TXT_HUDD_EFFIC); + break; + }; +} + +#ifdef MACINTOSH +#pragma export on +#endif + +// This function gets called by the game when it wants to learn some info about the game +void DLLFUNCCALL DLLGetGameInfo (tDLLOptions *options) +{ + options->flags = DOF_MAXTEAMS; + options->max_teams = 1; + strcpy(options->game_name,"Anarchy"); + strcpy(options->requirements,""); +} + +// Initializes the game function pointers +void DLLFUNCCALL DLLGameInit (int *api_func,ubyte *all_ok,int num_teams_to_use) +{ + *all_ok = 1; + DMFCBase = CreateDMFC(); + if(!DMFCBase) + { + *all_ok = 0; + return; + } + + dstat = CreateDmfcStats(); + if(!dstat) + { + *all_ok = 0; + return; + } + + DMFCBase->LoadFunctions(api_func); + + // Setup the event handlers that we handle + DMFCBase->Set_OnKeypress(OnKeypress); + DMFCBase->Set_OnHUDInterval(OnHUDInterval); + DMFCBase->Set_OnInterval(OnInterval); + DMFCBase->Set_OnClientPlayerKilled(OnClientPlayerKilled); + DMFCBase->Set_OnClientPlayerEntersGame(OnClientPlayerEntersGame); + DMFCBase->Set_OnClientLevelStart(OnClientLevelStart); + DMFCBase->Set_OnClientLevelEnd(OnClientLevelEnd); + DMFCBase->Set_OnServerGameCreated(OnServerGameCreated); + DMFCBase->Set_OnPLRInterval(OnPLRInterval); + DMFCBase->Set_OnPLRInit(OnPLRInit); + DMFCBase->Set_OnSaveStatsToFile(OnSaveStatsToFile); + DMFCBase->Set_OnLevelEndSaveStatsToFile(OnLevelEndSaveStatsToFile); + DMFCBase->Set_OnDisconnectSaveStatsToFile(OnDisconnectSaveStatsToFile); + DMFCBase->Set_OnPrintScores(OnPrintScores); + + + DLLCreateStringTable("Anarchy.str",&StringTable,&StringTableSize); + mprintf((0,"%d strings loaded from string table\n",StringTableSize)); + if(!StringTableSize){ + *all_ok = 0; + return; + } + + AnarchyGameInit(1); + + //add the death and suicide messages + DMFCBase->AddDeathMessage(TXT_DEATH1,true); + DMFCBase->AddDeathMessage(TXT_DEATH2,true); + DMFCBase->AddDeathMessage(TXT_DEATH3,false); + DMFCBase->AddDeathMessage(TXT_DEATH4,false); + DMFCBase->AddDeathMessage(TXT_DEATH5,true); + DMFCBase->AddDeathMessage(TXT_DEATH6,true); + DMFCBase->AddDeathMessage(TXT_DEATH7,false); + DMFCBase->AddDeathMessage(TXT_DEATH8,true); + DMFCBase->AddDeathMessage(TXT_DEATH9,true); + DMFCBase->AddDeathMessage(TXT_DEATH10,true); + + DMFCBase->AddSuicideMessage(TXT_SUICIDE1); + DMFCBase->AddSuicideMessage(TXT_SUICIDE2); + DMFCBase->AddSuicideMessage(TXT_SUICIDE3); + DMFCBase->AddSuicideMessage(TXT_SUICIDE4); + DMFCBase->AddSuicideMessage(TXT_SUICIDE5); + DMFCBase->AddSuicideMessage(TXT_SUICIDE6); + + DMFCBase->SetNumberOfTeams(1); + + netgame_info *Netgame = DMFCBase->GetNetgameInfo(); + Netgame->flags |= (NF_DAMAGE_FRIENDLY|NF_TRACK_RANK); + + Highlight_bmp = DLLbm_AllocBitmap(32,32,0); + if(Highlight_bmp>BAD_BITMAP_HANDLE){ + ushort *data = DLLbm_data(Highlight_bmp,0); + if(!data){ + //bail on out of here + *all_ok = 0; + return; + } + for(int x=0;x<32*32;x++){ + data[x] = GR_RGB16(50,50,50)|OPAQUE_FLAG; + } + } + + DMFCBase->AddHUDItemCallback(HI_TEXT,DisplayHUDScores); + + DisplayScoreScreen = false; + +} +// Called when the DLL is shutdown +void DLLFUNCCALL DLLGameClose () +{ + if(Highlight_bmp>BAD_BITMAP_HANDLE) + DLLbm_FreeBitmap(Highlight_bmp); + + DLLDestroyStringTable(StringTable,StringTableSize); + + if(dstat) + { + dstat->DestroyPointer(); + dstat = NULL; + } + + if(DMFCBase) + { + AnarchyGameClose(); + DMFCBase->GameClose(); + DMFCBase->DestroyPointer(); + DMFCBase = NULL; + } +} + +void DetermineScore(int precord_num,int column_num,char *buffer,int buffer_size) +{ + player_record *pr = DMFCBase->GetPlayerRecord(precord_num); + if(!pr || pr->state==STATE_EMPTY){ + buffer[0] = '\0'; + return; + } + + sprintf(buffer,"%d", pr->dstats.kills[DSTAT_LEVEL]-pr->dstats.suicides[DSTAT_LEVEL]); +} + +void AnarchyGameClose(void) +{ +} + +// DMFCApp::GameInit +// +// Sets up all the DLL functions and pointers and preps the class for use. This ABSOLUTLY must be +// called, so if you override DMFCApp::GameInit, make sure that you put a call to this somewhere in +// the override. +void AnarchyGameInit(int teams) +{ + //add the anarchy menu/submenus + IMenuItem *lev1,*lev2; + + lev1 = CreateMenuItemWArgs("Anarchy",MIT_NORMAL,0,NULL); + + lev2 = CreateMenuItemWArgs(TXT_MNU_HUDSTYLE,MIT_STATE,0,SwitchAnarchyScores); + lev2->SetStateItemList(3,TXT_NONE,TXT_SCOREHD,TXT_EFFICIENCY); + lev2->SetState(1); + lev1->AddSubMenu(lev2); + + lev2 = CreateMenuItemWArgs(TXT_MNU_HUDCOLOR,MIT_STATE,0,SwitchHUDColor); + lev2->SetStateItemList(2,TXT_PLAYERCOLORS,TXT_NORMAL); + lev2->SetState(HUD_color_model); + lev1->AddSubMenu(lev2); + + lev2 = DMFCBase->GetOnScreenMenu(); + lev2->AddSubMenu(lev1); + + DMFCBase->GameInit(teams); + + // Initialize the Stats Manager + // ---------------------------- + + tDmfcStatsInit tsi; + tDmfcStatsColumnInfo pl_col[6]; + char gname[20]; + strcpy(gname,"Anarchy"); + + tsi.flags = DSIF_SHOW_PIC|DSIF_SHOW_OBSERVERICON; + tsi.cColumnCountDetailed = 0; + tsi.cColumnCountPlayerList = 6; + tsi.clbDetailedColumn = NULL; + tsi.clbDetailedColumnBMP = NULL; + tsi.clbPlayerColumn = DetermineScore; + tsi.clbPlayerColumnBMP = NULL; + tsi.DetailedColumns = NULL; + tsi.GameName = gname; + tsi.MaxNumberDisplayed = NULL; + tsi.PlayerListColumns = pl_col; + tsi.SortedPlayerRecords = SortedPlayers; + + pl_col[0].color_type = DSCOLOR_SHIPCOLOR; + strcpy(pl_col[0].title,TXT_PILOT); + pl_col[0].type = DSCOL_PILOT_NAME; + pl_col[0].width = 120; + + pl_col[1].color_type = DSCOLOR_SHIPCOLOR; + strcpy(pl_col[1].title,TXT_SCORE); + pl_col[1].type = DSCOL_CUSTOM; + pl_col[1].width = 50; + + pl_col[2].color_type = DSCOLOR_SHIPCOLOR; + strcpy(pl_col[2].title,TXT_KILLS_SHORT); + pl_col[2].type = DSCOL_KILLS_LEVEL; + pl_col[2].width = 50; + + pl_col[3].color_type = DSCOLOR_SHIPCOLOR; + strcpy(pl_col[3].title,TXT_DEATHS_SHORT); + pl_col[3].type = DSCOL_DEATHS_LEVEL; + pl_col[3].width = 60; + + pl_col[4].color_type = DSCOLOR_SHIPCOLOR; + strcpy(pl_col[4].title,TXT_SUICIDES_SHORT); + pl_col[4].type = DSCOL_SUICIDES_LEVEL; + pl_col[4].width = 65; + + pl_col[5].color_type = DSCOLOR_SHIPCOLOR; + strcpy(pl_col[5].title,TXT_PING); + pl_col[5].type = DSCOL_PING; + pl_col[5].width = 40; + + dstat->Initialize(&tsi); +} + +void OnHUDInterval(void) +{ + dstat->DoFrame(); + DMFCBase->DisplayOutrageLogo(); + DMFCBase->OnHUDInterval(); +} + +void OnInterval(void) +{ + DMFCBase->GetSortedPlayerSlots(SortedPlayers,MAX_PLAYER_RECORDS); + DMFCBase->OnInterval(); +} + +void OnKeypress(int key) +{ + dllinfo *Data = DMFCBase->GetDLLInfoCallData(); + + switch(key){ + case K_F7: + DisplayScoreScreen = !DisplayScoreScreen; + DMFCBase->EnableOnScreenMenu(false); + dstat->Enable(DisplayScoreScreen); + break; + case K_PAGEDOWN: + if(DisplayScoreScreen){ + dstat->ScrollDown(); + Data->iRet = 1; + } + break; + case K_PAGEUP: + if(DisplayScoreScreen){ + dstat->ScrollUp(); + Data->iRet = 1; + } + break; + case K_F6: + DisplayScoreScreen = false; + dstat->Enable(false); + break; + case K_ESC: + if(DisplayScoreScreen){ + dstat->Enable(false); + DisplayScoreScreen = false; + Data->iRet = 1; + } + break; + } + + DMFCBase->OnKeypress(key); +} + +// The server has just started, so clear out all the stats and game info +void OnServerGameCreated(void) +{ + DMFCBase->OnServerGameCreated(); +} + +// The server has started a new level, so clear out any scores needed to be reset +void OnClientLevelStart(void) +{ + for(int i=0;iOnClientLevelStart(); +} + +void OnClientLevelEnd(void) +{ + DMFCBase->OnClientLevelEnd(); +} + +// A new player has entered the game, zero their stats out +void OnClientPlayerEntersGame(int player_num) +{ + DMFCBase->OnClientPlayerEntersGame(player_num); + + if(player_num!=DMFCBase->GetPlayerNum()) + DisplayWelcomeMessage(player_num); + else + display_my_welcome = true; +} + +// We need to adjust the scores +void OnClientPlayerKilled(object *killer_obj,int victim_pnum) +{ + DMFCBase->OnClientPlayerKilled(killer_obj,victim_pnum); + player_record *kpr; + + int kpnum; + + if(killer_obj){ + if((killer_obj->type==OBJ_PLAYER)||(killer_obj->type==OBJ_GHOST)) + kpnum = killer_obj->id; + else if(killer_obj->type==OBJ_ROBOT || killer_obj->type == OBJ_BUILDING){ + //countermeasure kill + kpnum = DMFCBase->GetCounterMeasureOwner(killer_obj); + }else{ + kpnum = -1; + } + }else{ + kpnum = -1; + } + + kpr = DMFCBase->GetPlayerRecordByPnum(kpnum); + if(kpr){ + int goal; + if(DMFCBase->GetScoreLimit(&goal)){ + int score = kpr->dstats.kills[DSTAT_LEVEL] - kpr->dstats.suicides[DSTAT_LEVEL]; + if(score>=goal){ + DMFCBase->EndLevel(); + } + } + } +} + +bool compare_slots(int a,int b) +{ + int ascore,bscore; + player_record *apr,*bpr; + apr = DMFCBase->GetPlayerRecord(a); + bpr = DMFCBase->GetPlayerRecord(b); + if( !apr ) + return true; + if( !bpr ) + return false; + if( apr->state==STATE_EMPTY ) + return true; + if( bpr->state==STATE_EMPTY ) + return false; + if( (apr->state==STATE_INGAME) && (bpr->state==STATE_INGAME) ){ + //both players were in the game + ascore = apr->dstats.kills[DSTAT_LEVEL] - apr->dstats.suicides[DSTAT_LEVEL]; + bscore = bpr->dstats.kills[DSTAT_LEVEL] - bpr->dstats.suicides[DSTAT_LEVEL]; + return (ascorestate==STATE_INGAME) && (bpr->state==STATE_DISCONNECTED) ){ + //apr gets priority since he was in the game on exit + return false; + } + if( (apr->state==STATE_DISCONNECTED) && (bpr->state==STATE_INGAME) ){ + //bpr gets priority since he was in the game on exit + return true; + } + //if we got here then both players were disconnected + ascore = apr->dstats.kills[DSTAT_LEVEL] - apr->dstats.suicides[DSTAT_LEVEL]; + bscore = bpr->dstats.kills[DSTAT_LEVEL] - bpr->dstats.suicides[DSTAT_LEVEL]; + return (ascore=0 && compare_slots(tempsort[j],t); j--){ + tempsort[j+1] = tempsort[j]; + } + // insert + tempsort[j+1] = t; + } + + //copy the array over + memcpy(SortedPlayers,tempsort,DLLMAX_PLAYERS*sizeof(int)); + + DMFCBase->OnPLRInit(); +} + +void OnPLRInterval(void) +{ +#define PLAYERS_COL 130 +#define SCORE_COL 280 +#define DEATHS_COL 330 +#define SUICIDES_COL 390 +#define TOTAL_COL 460 + + DMFCBase->OnPLRInterval(); + + int y = 40; + + int height = DLLgrfont_GetHeight((DMFCBase->GetGameFontTranslateArray())[SMALL_UI_FONT_INDEX]) + 1; + DLLgrtext_SetFont((DMFCBase->GetGameFontTranslateArray())[SMALL_UI_FONT_INDEX]); + + //print out header + DLLgrtext_SetColor(GR_RGB(255,255,150)); + DLLgrtext_Printf(PLAYERS_COL,y,TXT_PILOT); + DLLgrtext_Printf(SCORE_COL,y,TXT_KILLS_SHORT); + DLLgrtext_Printf(DEATHS_COL,y,TXT_DEATHS_SHORT); + DLLgrtext_Printf(SUICIDES_COL,y,TXT_SUICIDES_SHORT); + DLLgrtext_Printf(TOTAL_COL,y,TXT_SCORE); + y+=height; + + //print out player stats + int rank = 1; + int slot,pnum; + player_record *pr; + + for(int i=0;iGetPlayerRecord(slot); + if((pr) && (pr->state!=STATE_EMPTY) ){ + + if(DMFCBase->IsPlayerDedicatedServer(pr)) + continue;//skip a dedicated server + + pnum=DMFCBase->WasPlayerInGameAtLevelEnd(slot); + if(pnum!=-1) + { + DLLgrtext_SetColor((DMFCBase->GetPlayerColors())[pnum]); + }else + { + DLLgrtext_SetColor(GR_RGB(128,128,128)); + } + + char temp[100]; + sprintf(temp,"%d)%s",rank,pr->callsign); + DMFCBase->ClipString(SCORE_COL - PLAYERS_COL - 10,temp,true); + DLLgrtext_Printf(PLAYERS_COL,y,"%s",temp); + + DLLgrtext_Printf(SCORE_COL,y,"%d",pr->dstats.kills[DSTAT_LEVEL]); + DLLgrtext_Printf(DEATHS_COL,y,"%d",pr->dstats.deaths[DSTAT_LEVEL]); + DLLgrtext_Printf(SUICIDES_COL,y,"%d",pr->dstats.suicides[DSTAT_LEVEL]); + DLLgrtext_Printf(TOTAL_COL,y,"%d",pr->dstats.kills[DSTAT_LEVEL]-pr->dstats.suicides[DSTAT_LEVEL]); + y+=height; + rank++; + + if(y>=440) + goto quick_exit; + + } + } + +quick_exit:; +} + + +void SaveStatsToFile(char *filename) +{ + CFILE *file; + DLLOpenCFILE(&file,filename,"wt"); + if(!file){ + mprintf((0,"Unable to open output file\n")); + return; + } + + //write out game stats + #define BUFSIZE 150 + char buffer[BUFSIZE]; + char tempbuffer[25]; + int sortedslots[MAX_PLAYER_RECORDS]; + player_record *pr,*dpr; + tPInfoStat stat; + int count,length,p; + + //sort the stats + DMFCBase->GetSortedPlayerSlots(sortedslots,MAX_PLAYER_RECORDS); + count = 1; + + sprintf(buffer,TXT_SAVE_HEADER,(DMFCBase->GetNetgameInfo())->name,(DMFCBase->GetCurrentMission())->cur_level); + DLLcf_WriteString(file,buffer); + + sprintf(buffer,TXT_SAVE_HEADERB); + DLLcf_WriteString(file,buffer); + sprintf(buffer,"-----------------------------------------------------------------------------------------------"); + DLLcf_WriteString(file,buffer); + + + for(int s=0;sGetPlayerRecord(p); + if( pr && pr->state!=STATE_EMPTY) { + + if(DMFCBase->IsPlayerDedicatedServer(pr)) + continue; //skip dedicated server + + memset(buffer,' ',BUFSIZE); + + sprintf(tempbuffer,"%d)",count); + memcpy(&buffer[0],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%s%s",(pr->state==STATE_INGAME)?"":"*",pr->callsign); + memcpy(&buffer[7],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d[%d]",pr->dstats.kills[DSTAT_LEVEL]-pr->dstats.suicides[DSTAT_LEVEL],pr->dstats.kills[DSTAT_OVERALL]-pr->dstats.suicides[DSTAT_OVERALL]); + memcpy(&buffer[36],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d[%d]",pr->dstats.kills[DSTAT_LEVEL],pr->dstats.kills[DSTAT_OVERALL]); + memcpy(&buffer[48],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d[%d]",pr->dstats.deaths[DSTAT_LEVEL],pr->dstats.deaths[DSTAT_OVERALL]); + memcpy(&buffer[60],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d[%d]",pr->dstats.suicides[DSTAT_LEVEL],pr->dstats.suicides[DSTAT_OVERALL]); + memcpy(&buffer[71],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%s",DMFCBase->GetTimeString(DMFCBase->GetTimeInGame(p))); + memcpy(&buffer[82],tempbuffer,strlen(tempbuffer)); + + int pos; + pos = 82 + strlen(tempbuffer) + 1; + if(posGetPlayerRecord(p); + if( pr && pr->state!=STATE_EMPTY) { + + if(DMFCBase->IsPlayerDedicatedServer(pr)) + continue; //skip dedicated server + + //Write out header + sprintf(buffer,"%d) %s%s",count,(pr->state==STATE_INGAME)?"":"*",pr->callsign); + DLLcf_WriteString(file,buffer); + length = strlen(buffer); + memset(buffer,'=',length); + buffer[length] = '\0'; + DLLcf_WriteString(file,buffer); + + //time in game + sprintf(buffer,TXT_SAVE_TIMEINGAME,DMFCBase->GetTimeString(DMFCBase->GetTimeInGame(p))); + DLLcf_WriteString(file,buffer); + + if(DMFCBase->FindPInfoStatFirst(p,&stat)){ + sprintf(buffer,TXT_SAVE_KILLERLIST); + DLLcf_WriteString(file,buffer); + + if(stat.slot!=p){ + memset(buffer,' ',BUFSIZE); + dpr = DMFCBase->GetPlayerRecord(stat.slot); + int pos; + + ASSERT(dpr!=NULL); + if(dpr){ + sprintf(tempbuffer,"%s",dpr->callsign); + memcpy(buffer,tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d",stat.kills); + memcpy(&buffer[30],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d",stat.deaths); + memcpy(&buffer[40],tempbuffer,strlen(tempbuffer)); + + pos = 40 + strlen(tempbuffer) + 1; + if(posFindPInfoStatNext(&stat)){ + if(stat.slot!=p){ + int pos; + memset(buffer,' ',BUFSIZE); + dpr = DMFCBase->GetPlayerRecord(stat.slot); + + if(dpr) + { + sprintf(tempbuffer,"%s",dpr->callsign); + memcpy(buffer,tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d",stat.kills); + memcpy(&buffer[30],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d",stat.deaths); + memcpy(&buffer[40],tempbuffer,strlen(tempbuffer)); + + pos = 40 + strlen(tempbuffer) + 1; + if(posFindPInfoStatClose(); + DLLcf_WriteString(file,""); //skip a line + count++; + } + } + + //done writing stats + DLLcfclose(file); + DLLAddHUDMessage(TXT_MSG_SAVESTATS); +} + +#define ROOTFILENAME "Anarchy" +void OnSaveStatsToFile(void) +{ + char filename[256]; + DMFCBase->GenerateStatFilename(filename,ROOTFILENAME,false); + SaveStatsToFile(filename); +} + +void OnLevelEndSaveStatsToFile(void) +{ + char filename[256]; + DMFCBase->GenerateStatFilename(filename,ROOTFILENAME,true); + SaveStatsToFile(filename); +} + +void OnDisconnectSaveStatsToFile(void) +{ + char filename[256]; + DMFCBase->GenerateStatFilename(filename,ROOTFILENAME,false); + SaveStatsToFile(filename); +} + +void OnPrintScores(int level) +{ + char buffer[256]; + char name[50]; + memset(buffer,' ',256); + + int t; + int pos[6]; + int len[6]; + pos[0] = 0; t = len[0] = 20; //give ample room for pilot name + pos[1] = pos[0] + t + 1; t = len[1] = strlen(TXT_POINTS); + pos[2] = pos[1] + t + 1; t = len[2] = strlen(TXT_KILLS_SHORT); + pos[3] = pos[2] + t + 1; t = len[3] = strlen(TXT_DEATHS_SHORT); + pos[4] = pos[3] + t + 1; t = len[4] = strlen(TXT_SUICIDES_SHORT); + pos[5] = pos[4] + t + 1; t = len[5] = strlen(TXT_PING); + + memcpy(&buffer[pos[0]],TXT_PILOT,strlen(TXT_PILOT)); + memcpy(&buffer[pos[1]],TXT_POINTS,len[1]); + memcpy(&buffer[pos[2]],TXT_KILLS_SHORT,len[2]); + memcpy(&buffer[pos[3]],TXT_DEATHS_SHORT,len[3]); + memcpy(&buffer[pos[4]],TXT_SUICIDES_SHORT,len[4]); + memcpy(&buffer[pos[5]],TXT_PING,len[5]); + buffer[pos[5]+len[5]+1] = '\n'; + buffer[pos[5]+len[5]+2] = '\0'; + DPrintf(buffer); + + int slot; + player_record *pr; + int pcount; + + if(level<0 || level>=MAX_PLAYER_RECORDS) + pcount = MAX_PLAYER_RECORDS; + else + pcount = level; + + int sortedplayers[MAX_PLAYER_RECORDS]; + DMFCBase->GetSortedPlayerSlots(sortedplayers,MAX_PLAYER_RECORDS); + + for(int i=0;iGetPlayerRecord(slot); + if((pr)&&(pr->state!=STATE_EMPTY)){ + + if(DMFCBase->IsPlayerDedicatedServer(pr)) + continue; //skip dedicated server + + sprintf(name,"%s%s:",(pr->state==STATE_DISCONNECTED)?"*":"",pr->callsign); + name[19] = '\0'; + + memset(buffer,' ',256); + t = strlen(name); memcpy(&buffer[pos[0]],name,(tdstats.kills[DSTAT_LEVEL]-pr->dstats.suicides[DSTAT_LEVEL]); + t = strlen(name); memcpy(&buffer[pos[1]],name,(tdstats.kills[DSTAT_LEVEL]); + t = strlen(name); memcpy(&buffer[pos[2]],name,(tdstats.deaths[DSTAT_LEVEL]); + t = strlen(name); memcpy(&buffer[pos[3]],name,(tdstats.suicides[DSTAT_LEVEL]); + t = strlen(name); memcpy(&buffer[pos[4]],name,(tstate==STATE_INGAME) + sprintf(name,"%.0f",(DMFCBase->GetNetPlayers())[pr->pnum].ping_time*1000.0f); + else + strcpy(name,"---"); + t = strlen(name); memcpy(&buffer[pos[5]],name,(tGetPlayerNum()); + display_my_welcome = false; + } + + if(DisplayScoreScreen) + return; + + int height = DLLgrfont_GetHeight((DMFCBase->GetGameFontTranslateArray())[HUD_FONT_INDEX]) + 3; + ubyte alpha = DMFCBase->ConvertHUDAlpha((ubyte)((DisplayScoreScreen)?128:255)); + int y = (DMFCBase->GetGameWindowH()/2) - ((height*5)/2); + int x = 520; + ddgr_color color; + + int rank = 1; + player_record *pr; + + //Display your Kills & Deaths on the top corners of the screen + pr = DMFCBase->GetPlayerRecordByPnum(DMFCBase->GetPlayerNum()); + if(pr){ + int y = 25,x; + int lwidth; + char buffer[20]; + + int w_kill,w_death,max_w; + w_kill = DLLgrtext_GetTextLineWidth(TXT_KILLS); + w_death = DLLgrtext_GetTextLineWidth(TXT_DEATHS); + max_w = max(w_kill,w_death); + + x = DMFCBase->GetGameWindowW() - DMFCBase->GetGameWindowW()*0.0078125f; + DLLgrtext_SetColor(GR_GREEN); + DLLgrtext_SetAlpha(alpha); + DLLgrtext_Printf(x-(max_w/2)-(w_kill/2),y,TXT_KILLS); + y+=height; + + sprintf(buffer,"%d",pr->dstats.kills[DSTAT_LEVEL]); + lwidth = DLLgrtext_GetTextLineWidth(buffer); + DLLgrtext_SetColor(GR_GREEN); + DLLgrtext_SetAlpha(alpha); + DLLgrtext_Printf(x-(max_w/2)-(lwidth/2),y,buffer); + y+=height+3; + + DLLgrtext_SetColor(GR_GREEN); + DLLgrtext_SetAlpha(alpha); + DLLgrtext_Printf(x - (max_w/2) - (w_death/2),y,TXT_DEATHS); + y+=height; + + sprintf(buffer,"%d",pr->dstats.deaths[DSTAT_LEVEL]); + lwidth = DLLgrtext_GetTextLineWidth(buffer); + DLLgrtext_SetColor(GR_GREEN); + DLLgrtext_SetAlpha(alpha); + DLLgrtext_Printf(x - (max_w/2) - (lwidth/2),y,buffer); + } + + int ESortedPlayers[DLLMAX_PLAYERS]; + + switch(Anarchy_hud_display){ + case AHD_NONE: + return; + break; + case AHD_EFFICIENCY: + DMFCBase->GetSortedPlayerSlots(ESortedPlayers,DLLMAX_PLAYERS); + break; + } + + char name[30]; + + //determine coordinates to use here + //we'll use a virtual width of 85 pixels on a 640x480 screen + //so first determine the new width + int name_width = 85.0f * DMFCBase->GetHudAspectX(); + int score_width = DLLgrtext_GetTextLineWidth("888"); + int name_x = DMFCBase->GetGameWindowW() - name_width - score_width - 10; + int score_x = DMFCBase->GetGameWindowW() - score_width - 5; + + for(int i=0;iGetPlayerRecord(slot); + + if((pr)&&(pr->state!=STATE_EMPTY)){ + + if(DMFCBase->IsPlayerDedicatedServer(pr)) + continue; //skip dedicated server + + if( (pr->state==STATE_DISCONNECTED) || (pr->state==STATE_INGAME && !DMFCBase->IsPlayerObserver(pr->pnum)) ){ + + if(pr->pnum==DMFCBase->GetPlayerNum()){ + + switch(HUD_color_model){ + case ACM_PLAYERCOLOR: + color = (DMFCBase->GetPlayerColors())[pr->pnum]; + break; + case ACM_NORMAL: + color = GR_RGB(40,255,40); + break; + }; + + if(Highlight_bmp>BAD_BITMAP_HANDLE){ + //draw the highlite bar in the background + DLLrend_SetAlphaValue(alpha*0.50f); + DLLrend_SetZBufferState (0); + DLLrend_SetTextureType (TT_LINEAR); + DLLrend_SetLighting (LS_NONE); + DLLrend_SetAlphaType (AT_CONSTANT_TEXTURE); + DLLrend_DrawScaledBitmap(name_x-2,y-2,score_x+score_width+2,y+height-1,Highlight_bmp,0,0,1,1,1.0); + DLLrend_SetZBufferState (1); + } + + strcpy(name,pr->callsign); + DMFCBase->ClipString(name_width,name,true); + + DLLgrtext_SetAlpha(alpha); + DLLgrtext_SetColor(color); + DLLgrtext_Printf(name_x,y,"%s",name); + + if(Anarchy_hud_display==AHD_EFFICIENCY){ + float t = pr->dstats.kills[DSTAT_LEVEL]+pr->dstats.suicides[DSTAT_LEVEL]+pr->dstats.deaths[DSTAT_LEVEL]; + float value = (float)(pr->dstats.kills[DSTAT_LEVEL])/((t)?t:0.0000001f); + DLLgrtext_Printf(score_x,y,"%.1f",value); + }else{ + DLLgrtext_Printf(score_x,y,"%d",pr->dstats.kills[DSTAT_LEVEL]-pr->dstats.suicides[DSTAT_LEVEL]); + } + + y+=height; + }else + if(rank<6){ + + if(pr->state==STATE_DISCONNECTED){ + color = GR_GREY; + }else{ + switch(HUD_color_model){ + case ACM_PLAYERCOLOR: + color = (DMFCBase->GetPlayerColors())[pr->pnum]; + break; + case ACM_NORMAL: + color = GR_RGB(40,255,40); + break; + }; + } + strcpy(name,pr->callsign); + DMFCBase->ClipString(name_width,name,true); + + DLLgrtext_SetAlpha(alpha); + DLLgrtext_SetColor(color); + DLLgrtext_Printf(name_x,y,"%s",name); + + if(Anarchy_hud_display==AHD_EFFICIENCY){ + float t = pr->dstats.kills[DSTAT_LEVEL]+pr->dstats.suicides[DSTAT_LEVEL]+pr->dstats.deaths[DSTAT_LEVEL]; + float value = (float)(pr->dstats.kills[DSTAT_LEVEL])/((t)?t:0.0000001f); + DLLgrtext_Printf(score_x,y,"%.1f",value); + }else{ + DLLgrtext_Printf(score_x,y,"%d",pr->dstats.kills[DSTAT_LEVEL]-pr->dstats.suicides[DSTAT_LEVEL]); + } + + y+=height; + } + rank++; + } + } + } +} + +void DisplayWelcomeMessage(int player_num) +{ + char name_buffer[64]; + strcpy(name_buffer,(DMFCBase->GetPlayers())[player_num].callsign); + + if(player_num==DMFCBase->GetPlayerNum()) + { + DLLAddHUDMessage(TXT_WELCOME,name_buffer); + } + else + { + DLLAddHUDMessage(TXT_JOINED,name_buffer); + } +} + +void SwitchHUDColor(int i) +{ + if(i<0 || i>1) + return; + HUD_color_model = i; + + switch(HUD_color_model){ + case ACM_PLAYERCOLOR: + DLLAddHUDMessage(TXT_MSG_COLORPLR); + break; + case ACM_NORMAL: + DLLAddHUDMessage(TXT_MSG_COLORNORM); + break; + }; +} + +#ifdef MACINTOSH +#pragma export off +#endif \ No newline at end of file diff --git a/anarchy/anarchystr.h b/anarchy/anarchystr.h new file mode 100644 index 00000000..216a7bc7 --- /dev/null +++ b/anarchy/anarchystr.h @@ -0,0 +1,55 @@ +#ifndef __ANARCHY_STRING_TABLE_H_ +#define __ANARCHY_STRING_TABLE_H_ + +#define TXT(d) GetString(d) + + +#define TXT_DEATH1 TXT(0) //"%s got blasted by %s" +#define TXT_DEATH2 TXT(1) //"%s knows %s is his god" +#define TXT_DEATH3 TXT(2) //"%s sucks %s's milk" +#define TXT_DEATH4 TXT(3) //"%s realizes %s's power" +#define TXT_DEATH5 TXT(4) //"%s got killed by %s" +#define TXT_DEATH6 TXT(5) //"%s begs for %s's mercy" +#define TXT_DEATH7 TXT(6) //"%s realizes %s is a better player" +#define TXT_DEATH8 TXT(7) //"%s was no match for %s" +#define TXT_DEATH9 TXT(8) //"%s wishes he was as good as %s" +#define TXT_DEATH10 TXT(9) //"%s got messed up by %s" +#define TXT_SUICIDE1 TXT(10) //"%s blasts himself" +#define TXT_SUICIDE2 TXT(11) //"%s Bursts his own bubble" +#define TXT_SUICIDE3 TXT(12) //"%s doesn't know his own strength" +#define TXT_SUICIDE4 TXT(13) //"No prize for %s" +#define TXT_SUICIDE5 TXT(14) //"%s doesn't wish to live anymore" +#define TXT_SUICIDE6 TXT(15) //"%s SUCKS!" +#define TXT_PILOT TXT(16) //"Pilot" +#define TXT_KILLS TXT(17) //"Kills" +#define TXT_DEATHS TXT(18) //"Deaths" +#define TXT_SUICIDES TXT(19) //"Suicides" +#define TXT_SCORE TXT(20) //"Score" +#define TXT_STATS TXT(21) //"Stats" +#define TXT_WELCOME TXT(22) //"Welcome to the Anarchy %s!" +#define TXT_JOINED TXT(23) //"%s has joined the Anarchy" +#define TXT_POINTS TXT(24) //"Points" +#define TXT_HUDD_NONE TXT(25) //"Anarchy: HUD Display set to None" +#define TXT_HUDD_SCORES TXT(26) //"Anarchy: HUD Display set to Scores" +#define TXT_HUDD_EFFIC TXT(27) //"Anarchy: HUD Display set to Efficiency" +#define TXT_MNU_HUDSTYLE TXT(28) //"HUD Display" +#define TXT_NONE TXT(29) //"None" +#define TXT_SCOREHD TXT(30) //"Score" +#define TXT_EFFICIENCY TXT(31) //"Efficiency" +#define TXT_MNU_HUDCOLOR TXT(32) //"HUD Score Colors" +#define TXT_PLAYERCOLORS TXT(33) //"Player Colors" +#define TXT_NORMAL TXT(34) //"Normal" +#define TXT_PING TXT(35) //"Ping" +#define TXT_SAVE_HEADER TXT(36) //"Anarchy\r\nGame: %s\r\nLevel: %d\r\n" +#define TXT_SAVE_HEADERB TXT(37) //"[Rank] [Name] [Score] [Kills] [Deaths] [Suicides] [Time In Game]" +#define TXT_SAVE_HEADERC TXT(38) //"\r\nIndividual Stats\r\n" +#define TXT_SAVE_TIMEINGAME TXT(39) //"Total Time In Game: %s" +#define TXT_SAVE_KILLERLIST TXT(40) //"Callsign: Kills: Deaths:" +#define TXT_MSG_SAVESTATS TXT(41) //"Stats saved to file" +#define TXT_MSG_COLORPLR TXT(42) //"Anarchy HUD Color Model: Player Colors" +#define TXT_MSG_COLORNORM TXT(43) //"Anarchy HUD Color Model: Normal" +#define TXT_KILLS_SHORT TXT(44) //"K" +#define TXT_DEATHS_SHORT TXT(45) //"D" +#define TXT_SUICIDES_SHORT TXT(46) //"S" + +#endif diff --git a/briefinglocalizer/StdAfx.cpp b/briefinglocalizer/StdAfx.cpp new file mode 100644 index 00000000..ae1a708d --- /dev/null +++ b/briefinglocalizer/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// briefinglocalizer.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/briefinglocalizer/StdAfx.h b/briefinglocalizer/StdAfx.h new file mode 100644 index 00000000..951c3b44 --- /dev/null +++ b/briefinglocalizer/StdAfx.h @@ -0,0 +1,26 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__3C009907_F349_11D2_8F49_00104B27BFF0__INCLUDED_) +#define AFX_STDAFX_H__3C009907_F349_11D2_8F49_00104B27BFF0__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__3C009907_F349_11D2_8F49_00104B27BFF0__INCLUDED_) diff --git a/briefinglocalizer/briefinglocalizer.cpp b/briefinglocalizer/briefinglocalizer.cpp new file mode 100644 index 00000000..4b305f56 --- /dev/null +++ b/briefinglocalizer/briefinglocalizer.cpp @@ -0,0 +1,65 @@ +// briefinglocalizer.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "briefinglocalizer.h" +#include "briefinglocalizerDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBriefinglocalizerApp + +BEGIN_MESSAGE_MAP(CBriefinglocalizerApp, CWinApp) + //{{AFX_MSG_MAP(CBriefinglocalizerApp) + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBriefinglocalizerApp construction + +CBriefinglocalizerApp::CBriefinglocalizerApp() +{ +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CBriefinglocalizerApp object + +CBriefinglocalizerApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CBriefinglocalizerApp initialization + +BOOL CBriefinglocalizerApp::InitInstance() +{ + // Standard initialization + + SetRegistryKey(_T("Descent 3 Briefing Localizer")); + AfxInitRichEdit( ); + + +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + CBriefinglocalizerDlg dlg; + m_pMainWnd = &dlg; + int nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + } + else if (nResponse == IDCANCEL) + { + } + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} diff --git a/briefinglocalizer/briefinglocalizer.h b/briefinglocalizer/briefinglocalizer.h new file mode 100644 index 00000000..9c09a6c0 --- /dev/null +++ b/briefinglocalizer/briefinglocalizer.h @@ -0,0 +1,47 @@ +// briefinglocalizer.h : main header file for the BRIEFINGLOCALIZER application +// + +#if !defined(AFX_BRIEFINGLOCALIZER_H__3C009903_F349_11D2_8F49_00104B27BFF0__INCLUDED_) +#define AFX_BRIEFINGLOCALIZER_H__3C009903_F349_11D2_8F49_00104B27BFF0__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CBriefinglocalizerApp: +// See briefinglocalizer.cpp for the implementation of this class +// + +class CBriefinglocalizerApp : public CWinApp +{ +public: + CBriefinglocalizerApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBriefinglocalizerApp) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + +// Implementation + + //{{AFX_MSG(CBriefinglocalizerApp) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BRIEFINGLOCALIZER_H__3C009903_F349_11D2_8F49_00104B27BFF0__INCLUDED_) diff --git a/briefinglocalizer/briefinglocalizer.rc b/briefinglocalizer/briefinglocalizer.rc new file mode 100644 index 00000000..6200ebb8 --- /dev/null +++ b/briefinglocalizer/briefinglocalizer.rc @@ -0,0 +1,185 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif //_WIN32\r\n" + "#include ""res\\briefinglocalizer.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON DISCARDABLE "res\\briefinglocalizer.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_BRIEFINGLOCALIZER_DIALOG DIALOGEX 0, 0, 320, 200 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW +CAPTION "Outrage Briefing file localizer" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "&Previous",IDC_PREV,101,151,50,14 + PUSHBUTTON "&Next",IDC_NEXT,167,151,50,14 + PUSHBUTTON "&Save",IDC_SAVE,92,179,50,14 + PUSHBUTTON "&Quit",IDC_QUIT,177,179,50,14 + LTEXT "Title:",IDC_STATIC,7,9,16,8 + EDITTEXT IDC_TITLE,26,7,287,14,ES_AUTOHSCROLL + LTEXT "Text:",IDC_STATIC,151,30,17,8 + CONTROL "",IDC_TEXT,"RICHEDIT",ES_MULTILINE | ES_AUTOVSCROLL | + ES_WANTRETURN | WS_BORDER | WS_VSCROLL | WS_TABSTOP,7,39, + 306,105 +END + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "Outrage Entertainment\0" + VALUE "FileDescription", "Descent 3 Briefing Localizer\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "Descent 3 Briefing Localizer\0" + VALUE "LegalCopyright", "Copyright (C) 1999 Outrage Entertainment\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "briefinglocalizer.EXE\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "Descent 3 Briefing Localizer\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_BRIEFINGLOCALIZER_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 313 + TOPMARGIN, 7 + BOTTOMMARGIN, 193 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +#include "res\briefinglocalizer.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/briefinglocalizer/briefinglocalizerDlg.cpp b/briefinglocalizer/briefinglocalizerDlg.cpp new file mode 100644 index 00000000..e12004f0 --- /dev/null +++ b/briefinglocalizer/briefinglocalizerDlg.cpp @@ -0,0 +1,449 @@ +// briefinglocalizerDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "briefinglocalizer.h" +#include "briefinglocalizerDlg.h" + +#include +#include +#include +#include + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define TITLE_TAG "$title \"" +#define TITLE_TAG_LENGTH strlen(TITLE_TAG) + +#define TEXT_START_TAG "$text" +#define TEXT_START_TAG_LEN strlen(TEXT_START_TAG) + +#define TEXT_SHOW_TAG "show" +#define TEXT_SHOW_TAG_LEN strlen(TEXT_SHOW_TAG) + + +#define TEXT_END_TAG "$endtext" +#define TEXT_END_TAG_TAG_LEN strlen(TEXT_END_TAG) + +#define FIND_NEXT_LINE(a,b) do{ while( ((b[a]==0x0a) || (b[a]==0x0d)) && (a<(b).GetLength()) ) a++; }while(0) +//a = (b).FindOneOf("\x0a\x0d"); if(a!=-1) +///////////////////////////////////////////////////////////////////////////// +// CBriefinglocalizerDlg dialog + +CBriefinglocalizerDlg::CBriefinglocalizerDlg(CWnd* pParent /*=NULL*/) + : CDialog(CBriefinglocalizerDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBriefinglocalizerDlg) + m_Title = _T(""); + m_Text = _T(""); + //}}AFX_DATA_INIT + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); + m_FileChanged = false; + m_CurTextLeft = 0; + m_CurTextRight = 0; + m_BigStringTextLower.Empty(); + m_BigTextString.Empty(); +} + +void CBriefinglocalizerDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBriefinglocalizerDlg) + DDX_Control(pDX, IDC_TEXT, m_RichText); + DDX_Text(pDX, IDC_TITLE, m_Title); + DDX_Text(pDX, IDC_TEXT, m_Text); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CBriefinglocalizerDlg, CDialog) + //{{AFX_MSG_MAP(CBriefinglocalizerDlg) + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + ON_BN_CLICKED(IDC_NEXT, OnNext) + ON_BN_CLICKED(IDC_PREV, OnPrev) + ON_BN_CLICKED(IDC_QUIT, OnQuit) + ON_BN_CLICKED(IDC_SAVE, OnSave) + ON_EN_KILLFOCUS(IDC_TITLE, OnKillfocusTitle) + ON_EN_CHANGE(IDC_TEXT, OnChangeText) + ON_EN_CHANGE(IDC_TITLE, OnChangeTitle) + ON_NOTIFY(NM_KILLFOCUS, IDC_TEXT, OnKillfocusText) + ON_NOTIFY(EN_KILLFOCUS, IDC_TEXT, OnKillfocusText) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBriefinglocalizerDlg message handlers + +BOOL CBriefinglocalizerDlg::OnInitDialog() +{ + static char sztemppath[_MAX_PATH*2] = "."; + static char sztempfile[_MAX_PATH*2] = "tempfile.tmp"; + char path[_MAX_PATH*2]; + char drive[10]; + CString savepath; + CString DefaultPath; + + CDialog::OnInitDialog(); + + + m_RichText.SetEventMask(ENM_CHANGE); + + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + CFileDialog *fd; + + + DefaultPath = AfxGetApp()->GetProfileString("Defaults","LastDir",""); + + static char szFilter[] = "Descent 3 Briefing (*.br?)|*.br?|All Files (*.*)|*.*||"; + + _chdir(DefaultPath); + fd = new CFileDialog(true,".brf",NULL,OFN_FILEMUSTEXIST|OFN_HIDEREADONLY,szFilter); + if (fd->DoModal() == IDCANCEL) + { + delete fd; + CDialog::OnCancel(); + return FALSE; + } + + GetTempPath(_MAX_PATH*2,sztemppath); + + m_RealFileName = fd->GetPathName(); + + _splitpath(m_RealFileName,drive,path,NULL,NULL); + + + savepath = drive; + savepath += path; + + AfxGetApp()->WriteProfileString("Defaults","LastDir",savepath); + + GetTempFileName(sztemppath,"d3brf",0x42,sztempfile); + + m_TempFileName = sztempfile; + + delete fd; + fd = NULL; + FILE *infile; + struct _stat buf; + int result = _stat( m_RealFileName, &buf ); + if(result!=0) + { + AfxMessageBox("Error: Cannot determine file size!",MB_OK|MB_ICONSTOP); + goto do_error; + } + infile = fopen(m_RealFileName,"rt"); + if(infile) + { + CString newtitle; + + newtitle.Format("Outrage Briefing file localizer -- %s",m_RealFileName); + SetWindowText(newtitle); + + char *szbuf; + szbuf = (char *)malloc(buf.st_size); + fread(szbuf,buf.st_size,1,infile); + fclose(infile); + m_BigTextString = szbuf; + m_BigStringTextLower = m_BigTextString; + + m_BigStringTextLower.MakeLower(); + + delete szbuf; + + m_TitleLeft = m_BigStringTextLower.Find(TITLE_TAG); + if(m_TitleLeft!=-1) + { + m_TitleRight = m_BigStringTextLower.Find("\"",m_TitleLeft+TITLE_TAG_LENGTH); + m_Title = m_BigTextString.Mid(TITLE_TAG_LENGTH+m_TitleLeft,(m_TitleRight-(m_TitleLeft+TITLE_TAG_LENGTH))); + } + else + { + AfxMessageBox("Warning: There is no title in this briefing file!",MB_OK); + GetDlgItem(IDC_TITLE)->EnableWindow(false); + } + + + //Now I need to find the first text item! + m_CurTextLeft = m_BigStringTextLower.Find(TEXT_START_TAG); + if(m_CurTextLeft!=-1) + { + m_CurTextLeft = m_BigStringTextLower.Find(TEXT_SHOW_TAG,m_CurTextLeft); + if(m_CurTextLeft!=-1) + { + m_CurTextRight = m_BigStringTextLower.Find(TEXT_END_TAG,m_CurTextLeft+TEXT_SHOW_TAG_LEN); + m_CurTextLeft += TEXT_SHOW_TAG_LEN; + FIND_NEXT_LINE(m_CurTextLeft,m_BigTextString); + m_Text = m_BigTextString.Mid(m_CurTextLeft,(m_CurTextRight-(m_CurTextLeft)-1)); + } + } + else + { + AfxMessageBox("Warning: There is no text in this briefing file!",MB_OK); + GetDlgItem(IDC_NEXT)->EnableWindow(false); + GetDlgItem(IDC_PREV)->EnableWindow(false); + GetDlgItem(IDC_TEXT)->EnableWindow(false); + } + + m_CurrentText = 1; + + //Disable the previous button + GetDlgItem(IDC_PREV)->EnableWindow(false); + + UpdateData(false); + + + return TRUE; // return TRUE unless you set the focus to a control + } +do_error: + + AfxMessageBox("Error: Cannot open specified file!",MB_OK|MB_ICONSTOP); + CDialog::OnCancel(); + return TRUE; + +} + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. + +void CBriefinglocalizerDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + } +} + +HCURSOR CBriefinglocalizerDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + +void CBriefinglocalizerDlg::OnNext() +{ + //Get the text out of the dialog... + UpdateData(true); + + CString left,right; + + left = m_BigTextString.Left(m_CurTextLeft); + right = m_BigTextString.Right(m_BigTextString.GetLength()-m_CurTextRight); + + m_BigTextString = left + m_Text + "\n" + right; + m_BigStringTextLower = m_BigTextString; + m_BigStringTextLower.MakeLower(); + + + m_CurTextRight = m_CurTextLeft + m_Text.GetLength(); + + int saveleft = m_CurTextLeft; + //Now I need to find the next text item! + m_CurTextLeft = m_BigStringTextLower.Find(TEXT_START_TAG,m_CurTextRight); + if(m_CurTextLeft!=-1) + { + m_CurTextLeft = m_BigStringTextLower.Find(TEXT_SHOW_TAG,m_CurTextLeft); + if(m_CurTextLeft!=-1) + { + m_CurTextRight = m_BigStringTextLower.Find(TEXT_END_TAG,m_CurTextLeft+TEXT_SHOW_TAG_LEN); + m_CurTextLeft += TEXT_SHOW_TAG_LEN; + FIND_NEXT_LINE(m_CurTextLeft,m_BigTextString); + m_Text = m_BigTextString.Mid(m_CurTextLeft,(m_CurTextRight-(m_CurTextLeft)-1)); + GetDlgItem(IDC_PREV)->EnableWindow(true); + m_CurrentText++; + } + } + else + { + m_CurTextLeft = saveleft; + GetDlgItem(IDC_NEXT)->EnableWindow(false); + } + UpdateData(false); + +} + +void CBriefinglocalizerDlg::OnPrev() +{ + UpdateData(true); + + CString left,right; + + left = m_BigTextString.Left(m_CurTextLeft); + right = m_BigTextString.Right(m_BigTextString.GetLength()-m_CurTextRight); + + m_BigTextString = left + m_Text + "\n" + right; + m_BigStringTextLower = m_BigTextString; + m_BigStringTextLower.MakeLower(); + + + m_CurTextRight = 0; + m_CurTextLeft = 0; + + m_CurrentText--; + + int count = 0; + //Rewind to the previous item + while(count!=m_CurrentText) + { + m_CurTextLeft = m_BigStringTextLower.Find(TEXT_START_TAG,m_CurTextRight); + if(m_CurTextLeft!=-1) + { + m_CurTextLeft = m_BigStringTextLower.Find(TEXT_SHOW_TAG,m_CurTextLeft); + if(m_CurTextLeft!=-1) + { + m_CurTextRight = m_BigStringTextLower.Find(TEXT_END_TAG,m_CurTextLeft+TEXT_SHOW_TAG_LEN); + m_CurTextLeft += TEXT_SHOW_TAG_LEN; + FIND_NEXT_LINE(m_CurTextLeft,m_BigTextString); + } + } + count++; + } + + m_Text = m_BigTextString.Mid(m_CurTextLeft,(m_CurTextRight-(m_CurTextLeft))); + + GetDlgItem(IDC_NEXT)->EnableWindow(true); + if(m_CurrentText<=1) + { + //Disable the previous button + GetDlgItem(IDC_PREV)->EnableWindow(false); + } + UpdateData(false); +} + +void CBriefinglocalizerDlg::OnQuit() +{ + //See if the file has changed since it was last saved + if(m_FileChanged) + { + int res = AfxMessageBox("Briefing has changed, would you like to save your changes?",MB_YESNOCANCEL); + switch(res) + { + case IDYES: + //Prompt to save if it has + OnSave(); + break; + case IDNO: + break; + case IDCANCEL: + return; + default: + return; + } + } + CDialog::OnCancel(); + +} + +void CBriefinglocalizerDlg::OnSave() +{ + //Update the big string + CString testfile; + FILE *outfile; + testfile = m_RealFileName;// + ".test"; + outfile = fopen(testfile,"wt"); + if(outfile) + { + fwrite(LPCSTR(m_BigTextString),m_BigTextString.GetLength(),1,outfile); + m_FileChanged = false; + fclose(outfile); + } + else + { + AfxMessageBox("Error: Unable to write to file!",MB_OK); + } + +} + +void CBriefinglocalizerDlg::OnKillfocusTitle() +{ + CString oldtitle = m_Title; + UpdateData(true); + + int titlelendelta = m_Title.GetLength()-oldtitle.GetLength(); + int titleleft=0; + int titleright=0; + CString left,right; + + titleleft = m_BigStringTextLower.Find(TITLE_TAG); + if(titleleft!=-1) + { + titleright = m_BigStringTextLower.Find("\"",titleleft+TITLE_TAG_LENGTH); + left = m_BigTextString.Left(titleleft+TITLE_TAG_LENGTH); + right = m_BigTextString.Right(m_BigTextString.GetLength()-(titleright+1)); + m_BigTextString = left + m_Title + "\"" + right ; + m_BigStringTextLower = m_BigTextString; + m_BigStringTextLower.MakeLower(); + m_CurTextLeft += titlelendelta; + m_CurTextRight += titlelendelta; + } + +} + +void CBriefinglocalizerDlg::OnCancel() +{ + //do nothing... we want to use OnQuit() + //CDialog::OnCancel(); +} + +void CBriefinglocalizerDlg::OnChangeText() +{ + m_FileChanged = true; + UpdateData(true); + + CString left,right; + + left = m_BigTextString.Left(m_CurTextLeft); + right = m_BigTextString.Right(m_BigTextString.GetLength()-m_CurTextRight); + + m_BigTextString = left + m_Text + "\n" + right; + m_BigStringTextLower = m_BigTextString; + m_BigStringTextLower.MakeLower(); + m_CurTextRight = m_CurTextLeft + m_Text.GetLength(); + +} + +void CBriefinglocalizerDlg::OnChangeTitle() +{ + m_FileChanged = true; +} + + +void CBriefinglocalizerDlg::OnKillfocusText(NMHDR* pNMHDR, LRESULT* pResult) +{ + UpdateData(true); + + CString left,right; + + left = m_BigTextString.Left(m_CurTextLeft); + right = m_BigTextString.Right(m_BigTextString.GetLength()-m_CurTextRight); + + m_BigTextString = left + m_Text + "\n" + right; + m_BigStringTextLower = m_BigTextString; + m_BigStringTextLower.MakeLower(); + m_CurTextRight = m_CurTextLeft + m_Text.GetLength(); + + *pResult = 0; +} diff --git a/briefinglocalizer/briefinglocalizerDlg.h b/briefinglocalizer/briefinglocalizerDlg.h new file mode 100644 index 00000000..9915cb0b --- /dev/null +++ b/briefinglocalizer/briefinglocalizerDlg.h @@ -0,0 +1,69 @@ +// briefinglocalizerDlg.h : header file +// + +#if !defined(AFX_BRIEFINGLOCALIZERDLG_H__3C009905_F349_11D2_8F49_00104B27BFF0__INCLUDED_) +#define AFX_BRIEFINGLOCALIZERDLG_H__3C009905_F349_11D2_8F49_00104B27BFF0__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +///////////////////////////////////////////////////////////////////////////// +// CBriefinglocalizerDlg dialog + +class CBriefinglocalizerDlg : public CDialog +{ +// Construction +public: + int m_TitleRight; + int m_TitleLeft; + int m_CurrentText; + CString m_BigStringTextLower; + int m_CurTextRight; + int m_CurTextLeft; + CString m_BigTextString; + CString m_TempFileName; + CString m_RealFileName; + bool m_FileChanged; + CBriefinglocalizerDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CBriefinglocalizerDlg) + enum { IDD = IDD_BRIEFINGLOCALIZER_DIALOG }; + CRichEditCtrl m_RichText; + CString m_Title; + CString m_Text; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBriefinglocalizerDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + HICON m_hIcon; + + // Generated message map functions + //{{AFX_MSG(CBriefinglocalizerDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + afx_msg void OnNext(); + afx_msg void OnPrev(); + afx_msg void OnQuit(); + afx_msg void OnSave(); + afx_msg void OnKillfocusTitle(); + virtual void OnCancel(); + afx_msg void OnChangeText(); + afx_msg void OnChangeTitle(); + afx_msg void OnKillfocusText(NMHDR* pNMHDR, LRESULT* pResult); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BRIEFINGLOCALIZERDLG_H__3C009905_F349_11D2_8F49_00104B27BFF0__INCLUDED_) diff --git a/briefinglocalizer/res/briefinglocalizer.ico b/briefinglocalizer/res/briefinglocalizer.ico new file mode 100644 index 00000000..7eef0bcb Binary files /dev/null and b/briefinglocalizer/res/briefinglocalizer.ico differ diff --git a/briefinglocalizer/res/briefinglocalizer.rc2 b/briefinglocalizer/res/briefinglocalizer.rc2 new file mode 100644 index 00000000..15da7cd2 --- /dev/null +++ b/briefinglocalizer/res/briefinglocalizer.rc2 @@ -0,0 +1,13 @@ +// +// BRIEFINGLOCALIZER.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/briefinglocalizer/resource.h b/briefinglocalizer/resource.h new file mode 100644 index 00000000..a0150f4d --- /dev/null +++ b/briefinglocalizer/resource.h @@ -0,0 +1,24 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by briefinglocalizer.rc +// +#define IDD_BRIEFINGLOCALIZER_DIALOG 102 +#define IDR_MAINFRAME 128 +#define IDC_PREV 1000 +#define IDC_NEXT 1001 +#define IDC_SAVE 1002 +#define IDC_QUIT 1003 +#define IDC_TEXT 1004 +#define IDC_TITLE 1005 +#define IDC_RICHEDIT2 1008 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1009 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/coop/Makefile b/coop/Makefile new file mode 100644 index 00000000..d25a6188 --- /dev/null +++ b/coop/Makefile @@ -0,0 +1,24 @@ +include ../../default.mak + +OBJS = coop.o +REFS = coop.cpp +LIBNAME = ../../netgames/co-op.d3m + +CDLFLAGS = $(CFLAGS) -fPIC +LDLFLAGS = -shared -ldl + +all: depall $(OBJS) + gcc $(LDLFLAGS) -o $(LIBNAME) $(OBJS) /usr/lib/dmfc.so + +depall: + $(CC) -E -M $(CFLAGS) $(DEFINES) $(REFS) > .depend + +clean: + rm -f $(OBJS) *~ $(LIBNAME) core + +%.o: %.cpp + $(CC) $(CDLFLAGS) $(DEFINES) -c $< -o $@ + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/coop/coop.cpp b/coop/coop.cpp new file mode 100644 index 00000000..f3699d67 --- /dev/null +++ b/coop/coop.cpp @@ -0,0 +1,859 @@ +/* +* $Logfile: /DescentIII/Main/coop/coop.cpp $ +* $Revision: 1.1.1.1 $ +* $Date: 2003-08-26 03:56:42 $ +* $Author: kevinb $ +* +* Co-Op Play +* +* $Log: not supported by cvs2svn $ + * + * 23 10/21/99 9:27p Jeff + * B.A. Macintosh code merge + * + * 22 7/12/99 1:17p Jeff + * added netgame flag NF_COOP + * + * 21 5/23/99 3:04a Jason + * fixed bug with player rankings not being updated correctly + * + * 20 5/19/99 3:53p Jeff + * fixed possible (???) bug with displaying hud names + * + * 19 5/12/99 11:04p Jeff + * dmfc and multiplayer games now have endian friendly packets (*whew*) + * + * 18 5/09/99 6:20a Jeff + * improved Entropy (added sounds, max virii per room). Fixed rendering + * bugs for other multiplayer dlls. + * + * 17 5/07/99 12:52p Jeff + * audio taunt icon is ppic if available. coop has hard max team set of 4 + * + * 16 5/02/99 8:39a Jeff + * made quick & dirty PLR for coop + * + * 15 4/23/99 6:15p Jeff + * fixed double calls to GameClose + * + * 14 4/23/99 12:43p Jeff + * forgot to call CloseGame + * + * 13 4/21/99 5:34p Jeff + * added requirements + * + * 12 4/19/99 6:07p Jeff + * compile for Linux + * + * 11 3/27/99 4:53p Jeff + * player rankings in multiplayer games implemented. Fixed join message + * so it doesn't get cut off + * + * 10 3/19/99 12:54p Jeff + * base support for requesting the number of teams for a multiplayer game + * + * 9 3/18/99 8:40p Jeff + * hi res font fixes + * + * 8 3/17/99 12:23p Jeff + * converted DMFC to be COM interface + * + * 7 3/01/99 4:17p Jeff + * added net flag whether buddy bot allowed + * + * 6 2/11/99 3:09p Jeff + * localized + * + * 5 2/11/99 12:49a Jeff + * changed names of exported variables + * + * 3 2/07/99 2:06a Jeff + * updated coop...fixed bug when getting countermeasure owner, if owner is + * observer + * + * 2 2/03/99 7:22p Jeff + * + * 1 2/03/99 7:19p Jeff +* +* $NoKeywords: $ +*/ + + +#include +#include +#include +#include "idmfc.h" +#include "coop.h" +#include "coopstr.h" +IDMFC *DMFCBase = NULL; +IDmfcStats *dstat = NULL; +player *dPlayers; + +typedef struct{ + int Score[2]; +}tPlayerStat; +int pack_pstat(tPlayerStat *user_info,ubyte *data) +{ + int count = 0; + MultiAddInt(user_info->Score[0],data,&count); + MultiAddInt(user_info->Score[1],data,&count); + return count; +} + +int unpack_pstat(tPlayerStat *user_info,ubyte *data) +{ + int count = 0; + user_info->Score[0] = MultiGetInt(data,&count); + user_info->Score[1] = MultiGetInt(data,&count); + return count; +} + + +/////////////////////////////////////////////// +//localization info +char **StringTable; +int StringTableSize = 0; +char *_ErrorString = "Missing String"; +char *GetStringFromTable(int d){if( (d<0) || (d>=StringTableSize) ) return _ErrorString; else return StringTable[d];} +/////////////////////////////////////////////// +int SortedPlayers[MAX_PLAYER_RECORDS]; +bool DisplayScoreScreen = false; +bool FirstFrame = false; +bool display_my_welcome = false; + +void DisplayWelcomeMessage(int player_num); +void DisplayHUDScores(struct tHUDItem *hitem); +int Highlight_bmp = -1; + +void OnPLRInterval(void); +void OnPLRInit(void); + +#ifdef MACINTOSH +#pragma export on +#endif + +void DetermineScore(int precord_num,int column_num,char *buffer,int buffer_size) +{ + player_record *pr = DMFCBase->GetPlayerRecord(precord_num); + if(!pr || pr->state==STATE_EMPTY){ + buffer[0] = '\0'; + return; + } + tPlayerStat *stat = (tPlayerStat *)pr->user_info; + + sprintf(buffer,"%d",stat->Score[DSTAT_LEVEL]); +} + +// This function gets called by the game when it wants to learn some info about the game +void DLLFUNCCALL DLLGetGameInfo (tDLLOptions *options) +{ + options->flags = DOF_MAXTEAMS; + options->max_teams = 1; + strcpy(options->game_name,TXT_COOP); + strcpy(options->requirements,"COOP"); +} + +// Initializes the game function pointers +void DLLFUNCCALL DLLGameInit (int *api_func,ubyte *all_ok,int num_teams_to_use) +{ + *all_ok = 1; + DMFCBase = CreateDMFC(); + if(!DMFCBase) + { + *all_ok = 0; + return; + } + + dstat = CreateDmfcStats(); + if(!dstat) + { + *all_ok = 0; + return; + } + + DMFCBase->LoadFunctions(api_func); + + //Setup event handlers + DMFCBase->Set_OnHUDInterval(OnHUDInterval); + DMFCBase->Set_OnInterval(OnInterval); + DMFCBase->Set_OnKeypress(OnKeypress); + DMFCBase->Set_OnClientPlayerEntersGame(OnClientPlayerEntersGame); + DMFCBase->Set_OnServerObjectKilled(OnServerObjectKilled); + DMFCBase->Set_OnClientObjectKilled(OnClientObjectKilled); + DMFCBase->Set_OnPlayerConnect(OnPlayerConnect); + DMFCBase->Set_OnServerGameCreated(OnServerGameCreated); + DMFCBase->Set_OnClientLevelStart(OnClientLevelStart); + DMFCBase->Set_OnGameStateRequest(OnGameStateRequest); + DMFCBase->Set_OnSaveStatsToFile(OnSaveStatsToFile); + DMFCBase->Set_OnLevelEndSaveStatsToFile(OnLevelEndSaveStatsToFile); + DMFCBase->Set_OnDisconnectSaveStatsToFile(OnDisconnectSaveStatsToFile); + DMFCBase->Set_OnPrintScores(OnPrintScores); + DMFCBase->Set_OnPLRInterval(OnPLRInterval); + DMFCBase->Set_OnPLRInit(OnPLRInit); + + dPlayers = DMFCBase->GetPlayers(); + + DLLCreateStringTable("Coop.str",&StringTable,&StringTableSize); + mprintf((0,"%d strings loaded from string table\n",StringTableSize)); + if(!StringTableSize){ + *all_ok = 0; + return; + } + + DMFCBase->GameInit(1); + + Highlight_bmp = DLLbm_AllocBitmap(32,32,0); + if(Highlight_bmp>BAD_BITMAP_HANDLE){ + ushort *data = DLLbm_data(Highlight_bmp,0); + if(!data){ + //bail on out of here + *all_ok = 0; + return; + } + for(int x=0;x<32*32;x++){ + data[x] = GR_RGB16(50,50,50)|OPAQUE_FLAG; + } + } + + DMFCBase->AddHUDItemCallback(HI_TEXT,DisplayHUDScores); + DMFCBase->SetupPlayerRecord(sizeof(tPlayerStat),(int (*)(void *,ubyte *))pack_pstat,(int (*)(void *,ubyte *))unpack_pstat); + DMFCBase->SetNumberOfTeams(1); + + netgame_info *netgameinfo = DMFCBase->GetNetgameInfo(); + netgameinfo->flags |= (NF_USE_ROBOTS|NF_RESPAWN_WAYPOINT|NF_ALLOWGUIDEBOT|NF_COOP); + netgameinfo->max_players = min(4,netgameinfo->max_players); + DMFCBase->SetMaxPlayerHardLimit(4); + + // Initialize the Stats Manager + // ---------------------------- + tDmfcStatsInit tsi; + tDmfcStatsColumnInfo pl_col[5]; + char gname[20]; + strcpy(gname,TXT_STATGAMENAME); + + tsi.flags = DSIF_SHOW_PIC|DSIF_SHOW_OBSERVERICON|DSIF_NOLASTKILLER|DSIF_NOLASTVICTIM|DSIF_NODETAILEDINFO|DSIF_SHOWPLAYERVIEW; + tsi.cColumnCountDetailed = 0; + tsi.cColumnCountPlayerList = 5; + tsi.clbDetailedColumn = NULL; + tsi.clbDetailedColumnBMP = NULL; + tsi.clbPlayerColumn = DetermineScore; + tsi.clbPlayerColumnBMP = NULL; + tsi.DetailedColumns = NULL; + tsi.GameName = gname; + tsi.MaxNumberDisplayed = NULL; + tsi.PlayerListColumns = pl_col; + tsi.SortedPlayerRecords = SortedPlayers; + + pl_col[0].color_type = DSCOLOR_SHIPCOLOR; + strcpy(pl_col[0].title,TXT_PILOT); + pl_col[0].type = DSCOL_PILOT_NAME; + pl_col[0].width = 84; + + pl_col[1].color_type = DSCOLOR_SHIPCOLOR; + strcpy(pl_col[1].title,TXT_KILLS); + pl_col[1].type = DSCOL_CUSTOM; + pl_col[1].width = 51; + + pl_col[2].color_type = DSCOLOR_SHIPCOLOR; + strcpy(pl_col[2].title,TXT_DEATHS); + pl_col[2].type = DSCOL_DEATHS_LEVEL; + pl_col[2].width = 64; + + pl_col[3].color_type = DSCOLOR_SHIPCOLOR; + strcpy(pl_col[3].title,TXT_SUICIDES); + pl_col[3].type = DSCOL_SUICIDES_LEVEL; + pl_col[3].width = 69; + + pl_col[4].color_type = DSCOLOR_SHIPCOLOR; + strcpy(pl_col[4].title,TXT_PING); + pl_col[4].type = DSCOL_PING; + pl_col[4].width = 40; + + dstat->Initialize(&tsi); +} +// Called when the DLL is shutdown +void DLLFUNCCALL DLLGameClose () +{ + if(Highlight_bmp>BAD_BITMAP_HANDLE) + DLLbm_FreeBitmap(Highlight_bmp); + + DLLDestroyStringTable(StringTable,StringTableSize); + + if(dstat) + { + dstat->DestroyPointer(); + dstat = NULL; + } + + if(DMFCBase) + { + DMFCBase->GameClose(); + DMFCBase->DestroyPointer(); + DMFCBase = NULL; + } +} + + +void OnHUDInterval(void) +{ + dstat->DoFrame(); + DMFCBase->DisplayOutrageLogo(); + DMFCBase->OnHUDInterval(); +} + +bool compare_slots(int a,int b) +{ + int ascore,bscore; + player_record *apr,*bpr; + tPlayerStat *astat,*bstat; + + apr = DMFCBase->GetPlayerRecord(a); + bpr = DMFCBase->GetPlayerRecord(b); + if( !apr ) + return true; + if( !bpr ) + return false; + if( apr->state==STATE_EMPTY ) + return true; + if( bpr->state==STATE_EMPTY ) + return false; + astat = (tPlayerStat *)apr->user_info; + bstat = (tPlayerStat *)bpr->user_info; + + if( (apr->state==STATE_INGAME) && (bpr->state==STATE_INGAME) ){ + //both players were in the game + ascore = (astat)?astat->Score[DSTAT_LEVEL]:0; + bscore = (bstat)?bstat->Score[DSTAT_LEVEL]:0; + return (ascorestate==STATE_INGAME) && (bpr->state==STATE_DISCONNECTED) ){ + //apr gets priority since he was in the game on exit + return false; + } + if( (apr->state==STATE_DISCONNECTED) && (bpr->state==STATE_INGAME) ){ + //bpr gets priority since he was in the game on exit + return true; + } + //if we got here then both players were disconnected + ascore = (astat)?astat->Score[DSTAT_LEVEL]:0; + bscore = (bstat)?bstat->Score[DSTAT_LEVEL]:0; + return (ascore=0 && compare_slots(SortedPlayers[j],t); j--){ + SortedPlayers[j+1] = SortedPlayers[j]; + } + // insert + SortedPlayers[j+1] = t; + } + + FirstFrame = true; + DMFCBase->OnInterval(); +} + +void OnKeypress(int key) +{ + dllinfo *Data = DMFCBase->GetDLLInfoCallData(); + + switch(key){ + case K_F7: + DisplayScoreScreen = !DisplayScoreScreen; + DMFCBase->EnableOnScreenMenu(false); + dstat->Enable(DisplayScoreScreen); + break; + case K_PAGEDOWN: + if(DisplayScoreScreen){ + dstat->ScrollDown(); + Data->iRet = 1; + } + break; + case K_PAGEUP: + if(DisplayScoreScreen){ + dstat->ScrollUp(); + Data->iRet = 1; + } + break; + case K_F6: + DisplayScoreScreen = false; + dstat->Enable(false); + break; + case K_ESC: + if(DisplayScoreScreen){ + dstat->Enable(false); + DisplayScoreScreen = false; + Data->iRet = 1; + } + break; + } + + DMFCBase->OnKeypress(key); +} + +void OnClientPlayerEntersGame(int player_num) +{ + if(player_num==DMFCBase->GetPlayerNum()){ + FirstFrame = false; + DisplayScoreScreen = false; + } + + DMFCBase->OnClientPlayerEntersGame(player_num); + + if(player_num!=DMFCBase->GetPlayerNum()) + DisplayWelcomeMessage(player_num); + else + display_my_welcome = true; +} + +// A new player has entered the game, zero there stats out +void OnPlayerConnect(int player_num) +{ + DMFCBase->OnPlayerConnect(player_num); + + tPlayerStat *stat = (tPlayerStat *)DMFCBase->GetPlayerRecordData(player_num); + if(stat){ + stat->Score[DSTAT_LEVEL] = 0; + stat->Score[DSTAT_OVERALL] = 0; + } +} + + +// The server has just started, so clear out all the stats and game info +void OnServerGameCreated(void) +{ + DMFCBase->OnServerGameCreated(); + player_record *pr; + tPlayerStat *stat; + for(int i=0;iGetPlayerRecord(i); + if(pr) + stat = (tPlayerStat *) pr->user_info; + else + stat = NULL; + if(stat){ + stat->Score[DSTAT_LEVEL] = 0; + stat->Score[DSTAT_OVERALL] = 0; + } + } +} + +// The server has started a new level, so clear out level scores +void OnClientLevelStart(void) +{ + DMFCBase->OnClientLevelStart(); + player_record *pr; + tPlayerStat *stat; + for(int i=0;iGetPlayerRecord(i); + if(pr) + stat = (tPlayerStat *)pr->user_info; + else + stat = NULL; + + if(stat){ + stat->Score[DSTAT_LEVEL] = 0; + } + } + DMFCBase->RequestGameState(); +} + +// We need to send all the inventory info out to the new player +void OnGameStateRequest(int player_num) +{ + DMFCBase->OnGameStateRequest(player_num); +} + +void DisplayWelcomeMessage(int player_num) +{ + char name_buffer[64]; + strcpy(name_buffer,(DMFCBase->GetPlayers())[player_num].callsign); + + if(player_num==DMFCBase->GetPlayerNum()) + { + DLLAddHUDMessage(TXT_WELCOME,name_buffer); + } + else + { + DLLAddHUDMessage(TXT_JOINED,name_buffer); + } +} + +void OnServerObjectKilled(object *obj,object *killer) +{ + if(!killer) + return; //can't handle this + + if(obj->type==OBJ_ROBOT || (obj->type == OBJ_BUILDING && obj->ai_info)){ + + //check to see if the killer is a player + bool ok_to_call = false; + + if(killer->type==OBJ_PLAYER){ + ok_to_call = true; + }else if(killer->type==OBJ_ROBOT){ + if(DMFCBase->GetCounterMeasureOwner(killer)!=-1){ + ok_to_call = true; + } + } + + if(ok_to_call){ + DMFCBase->CallClientEvent(EVT_CLIENT_GAMEOBJKILLED,DMFCBase->GetMeObjNum(),DMFCBase->GetItObjNum(),-1); + DMFCBase->CallOnClientObjectKilled(obj,killer); + } + } + + DMFCBase->OnServerObjectKilled(obj,killer); +} + +void OnClientObjectKilled(object *obj,object *killer) +{ + object *parent; + DLLGetUltimateParentForObject(&parent,killer); + + if((parent->type!=OBJ_PLAYER)&&(parent->type!=OBJ_OBSERVER)){ + mprintf((0,"Robot killed wasn't by a OBJ_PLAYER or OBJ_OBSERVER (%d)\n",parent->type)); + return; + } + + int killer_pnum = parent->id; + + player_record *pr = DMFCBase->GetPlayerRecordByPnum(killer_pnum); + if(!pr){ + mprintf((0,"Invalid player record!\n")); + Int3(); + return; + } + + tPlayerStat *stat = (tPlayerStat *)pr->user_info; + + stat->Score[DSTAT_LEVEL]++; + stat->Score[DSTAT_OVERALL]++; + + mprintf((0,"%s's score is now %d\n",dPlayers[killer_pnum].callsign,stat->Score[DSTAT_LEVEL])); + + DMFCBase->OnClientObjectKilled(obj,killer); +} + +void DisplayHUDScores(struct tHUDItem *hitem) +{ + if(!FirstFrame) + return; + + if(display_my_welcome) + { + DisplayWelcomeMessage(DMFCBase->GetPlayerNum()); + display_my_welcome = false; + } + + if(DisplayScoreScreen) + return; + + if(DMFCBase->IAmDedicatedServer()) + return; + + int old_font = DLLgrtext_GetFont(); + int start_y; + int i; + + DLLgrtext_SetFont((DMFCBase->GetGameFontTranslateArray())[HUD_FONT_INDEX]); + int height = DLLRenderHUDGetTextHeight("X") + 1; + int players_in_game = 0; + + for(i=0;iCheckPlayerNum(i) && !DMFCBase->IsPlayerDedicatedServer(i)){ + players_in_game++; + } + } + + if(players_in_game<=0) + return; + + players_in_game = min(players_in_game,8); + + start_y = (DMFCBase->GetGameWindowH()/2) - ((players_in_game*5)/2); + //determine coordinates to use here + //we'll use a virtual width of 85 pixels on a 640x480 screen + //so first determine the new width + int name_width = 85.0f * DMFCBase->GetHudAspectX(); + int name_x = DMFCBase->GetGameWindowW() - name_width - 10; + + int pnum,index = 0; + ubyte alpha = DMFCBase->ConvertHUDAlpha((ubyte)((DisplayScoreScreen)?128:255)); + + DLLgrtext_SetAlpha(alpha); + char name[64]; + + // Display only the players in the game + while( (players_in_game > 0) && (indexCheckPlayerNum(pnum) && !DMFCBase->IsPlayerDedicatedServer(pnum) ){ + //valid player + if(pnum==DMFCBase->GetPlayerNum()) + { + if(Highlight_bmp>BAD_BITMAP_HANDLE){ + //draw the highlite bar in the background + DLLrend_SetAlphaValue(alpha*0.50f); + DLLrend_SetZBufferState (0); + DLLrend_SetTextureType (TT_LINEAR); + DLLrend_SetLighting (LS_NONE); + DLLrend_SetAlphaType (AT_CONSTANT_TEXTURE); + + DLLrend_DrawScaledBitmap(name_x-2,start_y-2,DMFCBase->GetGameWindowW()-8,start_y+height+1,Highlight_bmp,0,0,1,1,1.0); + DLLrend_SetZBufferState (1); + } + } + + strcpy(name,dPlayers[pnum].callsign); + DMFCBase->ClipString(name_width,name,true); + + DLLgrtext_SetColor((DMFCBase->GetPlayerColors())[pnum]); + DLLgrtext_Printf(name_x,start_y,name); + + start_y += height; + players_in_game--; + } + index++; + } + + DLLgrtext_SetFont(old_font); +} + +void SaveStatsToFile(char *filename) +{ + /* + CFILE *file; + DLLOpenCFILE(&file,filename,"wt"); + if(!file){ + mprintf((0,"Unable to open output file\n")); + return; + } + + //write out game stats + #define BUFSIZE 150 + char buffer[BUFSIZE]; + char tempbuffer[25]; + int sortedslots[MAX_PLAYER_RECORDS]; + player_record *pr,*dpr; + tPInfoStat stat; + int count,length,p; + + count = 1; + + sprintf(buffer,TXT_SAVE_HEADER,Netgame->name,Current_mission->cur_level); + DLLcf_WriteString(file,buffer); + + sprintf(buffer,TXT_SAVE_HEADERB); + DLLcf_WriteString(file,buffer); + sprintf(buffer,"-----------------------------------------------------------------------------------"); + DLLcf_WriteString(file,buffer); + + + tPlayerStat *st; + for(int s=0;sstate!=STATE_EMPTY) { + + if(IsPlayerDedicatedServer(pr)) + continue; //skip dedicated server + + st = (tPlayerStat *)pr->user_info; + + memset(buffer,' ',BUFSIZE); + + sprintf(tempbuffer,"%d)",count); + memcpy(&buffer[0],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%s%s",(pr->state==STATE_INGAME)?"":"*",pr->callsign); + memcpy(&buffer[7],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d[%d]",st->Score[DSTAT_LEVEL],st->Score[DSTAT_OVERALL]); + memcpy(&buffer[36],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d[%d]",pr->dstats.deaths[DSTAT_LEVEL],pr->dstats.deaths[DSTAT_OVERALL]); + memcpy(&buffer[48],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d[%d]",pr->dstats.suicides[DSTAT_LEVEL],pr->dstats.suicides[DSTAT_OVERALL]); + memcpy(&buffer[60],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%s",GetTimeString(GetTimeInGame(p))); + memcpy(&buffer[71],tempbuffer,strlen(tempbuffer)); + + int pos; + pos = 71 + strlen(tempbuffer) + 1; + if(posGenerateStatFilename(filename,ROOTFILENAME,false); + SaveStatsToFile(filename); +} + +void OnLevelEndSaveStatsToFile(void) +{ + char filename[256]; + DMFCBase->GenerateStatFilename(filename,ROOTFILENAME,true); + SaveStatsToFile(filename); +} + +void OnDisconnectSaveStatsToFile(void) +{ + char filename[256]; + DMFCBase->GenerateStatFilename(filename,ROOTFILENAME,false); + SaveStatsToFile(filename); +} + +void OnPrintScores(int level) +{ + /* + char buffer[256]; + char name[50]; + memset(buffer,' ',256); + + int t; + int pos[5]; + int len[5]; + pos[0] = 0; t = len[0] = 20; //give ample room for pilot name + pos[1] = pos[0] + t + 1; t = len[1] = strlen(TXT_KILLS_SHORT); + pos[2] = pos[1] + t + 1; t = len[2] = strlen(TXT_DEATHS_SHORT); + pos[3] = pos[2] + t + 1; t = len[3] = strlen(TXT_SUICIDES_SHORT); + pos[4] = pos[3] + t + 1; t = len[4] = strlen(TXT_PING); + + memcpy(&buffer[pos[0]],TXT_PILOT,strlen(TXT_PILOT)); + memcpy(&buffer[pos[1]],TXT_KILLS_SHORT,len[1]); + memcpy(&buffer[pos[2]],TXT_DEATHS_SHORT,len[2]); + memcpy(&buffer[pos[3]],TXT_SUICIDES_SHORT,len[3]); + memcpy(&buffer[pos[4]],TXT_PING,len[4]); + buffer[pos[4]+len[4]+1] = '\n'; + buffer[pos[4]+len[4]+2] = '\0'; + DPrintf(buffer); + + int slot; + player_record *pr; + int pcount; + + if(level<0 || level>=MAX_PLAYER_RECORDS) + pcount = MAX_PLAYER_RECORDS; + else + pcount = level; + + tPlayerStat *st; + + for(int i=0;istate!=STATE_EMPTY)){ + + if(IsPlayerDedicatedServer(pr)) + continue; //skip dedicated server + + st = (tPlayerStat *)pr->user_info; + + sprintf(name,"%s%s:",(pr->state==STATE_DISCONNECTED)?"*":"",pr->callsign); + name[19] = '\0'; + + memset(buffer,' ',256); + t = strlen(name); memcpy(&buffer[pos[0]],name,(tScore[DSTAT_LEVEL]); + t = strlen(name); memcpy(&buffer[pos[1]],name,(tdstats.deaths[DSTAT_LEVEL]); + t = strlen(name); memcpy(&buffer[pos[2]],name,(tdstats.suicides[DSTAT_LEVEL]); + t = strlen(name); memcpy(&buffer[pos[3]],name,(tstate==STATE_INGAME) + sprintf(name,"%.0f",NetPlayers[pr->pnum].ping_time*1000.0f); + else + strcpy(name,"---"); + t = strlen(name); memcpy(&buffer[pos[4]],name,(tGetGametime(); +} + +void OnPLRInterval(void) +{ + level_info *li = DMFCBase->GetLevelInfo(); + + int height = DLLgrfont_GetHeight((DMFCBase->GetGameFontTranslateArray())[BIG_FONT_INDEX]); + DLLgrtext_SetFont((DMFCBase->GetGameFontTranslateArray())[BIG_FONT_INDEX]); + + int y = 240; + + float ft,newtime; + newtime = DMFCBase->GetGametime(); + ft = newtime - PLRLasttime; + PLRLasttime = newtime; + PLRElapsedtime += ft; + + float alpha; + + if(PLRElapsedtime>5.0f) + { + alpha = 1.0f; + } + else + { + alpha = (5.0f - PLRElapsedtime)/5.0f; + } + + DLLrend_ClearScreen(GR_BLACK); + DLLgrtext_SetColor(GR_RGB(40,40,255)); + DLLgrtext_CenteredPrintf(0,y-height-1,TXT_LEVELCOMPLETE); + + if(li) + { + DLLgrtext_SetAlpha((ubyte)(alpha*255.0f)); + DLLgrtext_SetColor(GR_RGB(255,255,255)); + DLLgrtext_CenteredPrintf(0,y+1,li->name); + } + + DLLgrtext_Flush(); +} + +#ifdef MACINTOSH +#pragma export off +#endif diff --git a/coop/coop.h b/coop/coop.h new file mode 100644 index 00000000..5c229f6b --- /dev/null +++ b/coop/coop.h @@ -0,0 +1,168 @@ +/* +* $Logfile: /DescentIII/Main/coop/coop.h $ +* $Revision: 1.1.1.1 $ +* $Date: 2003-08-26 03:56:42 $ +* $Author: kevinb $ +* +* Co-Op play +* +* $Log: not supported by cvs2svn $ + * + * 8 10/21/99 9:28p Jeff + * B.A. Macintosh code merge + * + * 7 3/22/99 5:51p Matt + * Removed some includes from one file and added some to other files, to + * reduce the amount of rebuilding when headers change. + * + * 6 3/19/99 12:54p Jeff + * base support for requesting the number of teams for a multiplayer game + * + * 5 3/17/99 12:23p Jeff + * converted DMFC to be COM interface + * + * 4 2/08/99 12:46a Jeff + * updated + * + * 3 2/07/99 2:06a Jeff + * updated coop...fixed bug when getting countermeasure owner, if owner is + * observer + * + * 2 2/03/99 8:48p Josh + * Luke: Checked in for Josh (copied from Jeff) so he could work + * + * 1 2/03/99 8:47p Josh +* +* $NoKeywords: $ +*/ + + +#ifndef __DMFC_APP_H_ +#define __DMFC_APP_H_ + +#include "osiris_share.h" +#include "d3events.h" + +void OnHUDInterval(void); +void OnInterval(void); +void OnKeypress(int key); +void OnClientPlayerEntersGame(int player_num); +void OnServerObjectKilled(object *obj,object *killer); +void OnClientObjectKilled(object *obj,object *killer); +void OnPlayerConnect(int player_num); +void OnServerGameCreated(void); +void OnClientLevelStart(void); +void OnGameStateRequest(int player_num); +void SaveStatsToFile(char *filename); +void OnSaveStatsToFile(void); +void OnLevelEndSaveStatsToFile(void); +void OnDisconnectSaveStatsToFile(void); +void OnPrintScores(int level); +extern IDMFC *DMFCBase; + +// These next two function prototypes MUST appear in the extern "C" block if called +// from a CPP file. +#ifdef __cplusplus +extern "C" +{ +#endif + DLLEXPORT void DLLFUNCCALL DLLGameInit (int *api_func,ubyte *all_ok,int num_teams_to_use); + DLLEXPORT void DLLFUNCCALL DLLGameCall (int eventnum,dllinfo *data); + DLLEXPORT void DLLFUNCCALL DLLGameClose (); + DLLEXPORT void DLLFUNCCALL DLLGetGameInfo (tDLLOptions *options); + DLLEXPORT int DLLFUNCCALL GetGOScriptID(char *name,ubyte isdoor); + DLLEXPORT void DLLFUNCCALLPTR CreateInstance(int id); + DLLEXPORT void DLLFUNCCALL DestroyInstance(int id,void *ptr); + DLLEXPORT short DLLFUNCCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data); + DLLEXPORT int DLLFUNCCALL SaveRestoreState( void *file_ptr, ubyte saving_state ); +#ifdef __cplusplus +} +#endif + +#ifdef MACINTOSH +#pragma export on +#endif + +// The main entry point where the game calls the dll +void DLLFUNCCALL DLLGameCall (int eventnum,dllinfo *data) +{ + if((eventnumGetLocalRole()!=LR_SERVER)){ + return; + } + + DMFCBase->TranslateEvent(eventnum,data); +} + +// GetGOScriptID +// Purpose: +// Given the name of the object (from it's pagename), this function will search through it's +// list of General Object Scripts for a script with a matching name (to see if there is a script +// for that type/id of object within this DLL). If a matching scriptname is found, a UNIQUE ID +// is to be returned back to Descent 3. This ID will be used from here on out for all future +// interaction with the DLL. Since doors are not part of the generic object's, it's possible +// for a door to have the same name as a generic object (OBJ_POWERUP, OBJ_BUILDING, OBJ_CLUTTER +// or OBJ_ROBOT), therefore, a 1 is passed in for isdoor if the given object name refers to a +// door, else it is a 0. The return value is the unique identifier, else -1 if the script +// does not exist in the DLL. +int DLLFUNCCALL GetGOScriptID(char *name,ubyte isdoor) +{ + return -1; +} + +// CreateInstance +// Purpose: +// Given an ID from a call to GetGOScriptID(), this function will create a new instance for that +// particular script (by allocating and initializing memory, etc.). A pointer to this instance +// is to be returned back to Descent 3. This pointer will be passed around, along with the ID +// for CallInstanceEvent() and DestroyInstance(). Return NULL if there was an error. +void DLLFUNCCALLPTR CreateInstance(int id) +{ + return NULL; +} + +// DestroyInstance +// Purpose: +// Given an ID, and a pointer to a particular instance of a script, this function will delete and +// destruct all information associated with that script, so it will no longer exist. +void DLLFUNCCALL DestroyInstance(int id,void *ptr) +{ +} + +// CallInstanceEvent +// Purpose: +// Given an ID, a pointer to a script instance, an event and a pointer to the struct of +// information about the event, this function will translate who this event belongs to and +// passes the event to that instance of the script to be handled. Return a combination of +// CONTINUE_CHAIN and CONTINUE_DEFAULT, to give instructions on what to do based on the +// event. CONTINUE_CHAIN means to continue through the chain of scripts (custom script, level +// script, mission script, and finally default script). If CONTINUE_CHAIN is not specified, +// than the chain is broken and those scripts of lower priority will never get the event. Return +// CONTINUE_DEFAULT in order to tell D3 if you want process the normal action that is built into +// the game for that event. This only pertains to certain events. If the chain continues +// after this script, than the CONTINUE_DEFAULT setting will be overridden by lower priority +// scripts return value. +short DLLFUNCCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data) +{ + return CONTINUE_CHAIN|CONTINUE_DEFAULT; +} + +// SaveRestoreState +// Purpose: +// This function is called when Descent 3 is saving or restoring the game state. In this function +// you should save/restore any global data that you want preserved through load/save (which includes +// demos). You must be very careful with this function, corrupting the file (reading or writing too +// much or too little) may be hazardous to the game (possibly making it impossible to restore the +// state). It would be best to use version information to keep older versions of saved states still +// able to be used. IT IS VERY IMPORTANT WHEN SAVING THE STATE TO RETURN THE NUMBER OF _BYTES_ WROTE +// TO THE FILE. When restoring the data, the return value is ignored. saving_state is 1 when you should +// write data to the file_ptr, 0 when you should read in the data. +int DLLFUNCCALL SaveRestoreState( void *file_ptr, ubyte saving_state ) +{ + return 0; +} + +#ifdef MACINTOSH +#pragma export off +#endif + +#endif diff --git a/coop/coopstr.h b/coop/coopstr.h new file mode 100644 index 00000000..2c14b641 --- /dev/null +++ b/coop/coopstr.h @@ -0,0 +1,23 @@ +//Defines for indexes into the string table for in-code strings + +#ifndef __STRING_TABLE____ +#define __STRING_TABLE____ + +#define TXT(index) GetStringFromTable(index) + +//Returns a pointer to the string at the index location from the string table +//if it is a bad index given, then the pointer to the error string "ERROR MISSING STRING" is given + +char *GetStringFromTable(int index); + +#define TXT_COOP TXT(0) //"Coop" +#define TXT_STATGAMENAME TXT(1) //"Co-op Descent 3" +#define TXT_PILOT TXT(2) //"Pilot" +#define TXT_KILLS TXT(3) //"Kills" +#define TXT_DEATHS TXT(4) //"Deaths" +#define TXT_SUICIDES TXT(5) //"Suicides" +#define TXT_PING TXT(6) //"Ping" +#define TXT_WELCOME TXT(7) //"Welcome to the Co-Op Game %s" +#define TXT_JOINED TXT(8) //"%s has joined the game" +#define TXT_LEVELCOMPLETE TXT(9) //"Level Completed!" +#endif diff --git a/ctf/CTFstr.h b/ctf/CTFstr.h new file mode 100644 index 00000000..ac49c5a0 --- /dev/null +++ b/ctf/CTFstr.h @@ -0,0 +1,53 @@ +#ifndef __CTF_STR_H_ +#define __CTF_STR_H_ + +#define TXT(d) GetString(d) + +#define TXT_DEATH1 TXT(0) //"%s got blasted by %s" +#define TXT_DEATH2 TXT(1) //"%s knows %s is his god" +#define TXT_DEATH3 TXT(2) //"%s sucks %s's milk" +#define TXT_DEATH4 TXT(3) //"%s realizes %s's power" +#define TXT_DEATH5 TXT(4) //"%s got killed by %s" +#define TXT_DEATH6 TXT(5) //"%s begs for %s's mercy" +#define TXT_DEATH7 TXT(6) //"%s realizes %s is a better player" +#define TXT_DEATH8 TXT(7) //"%s was no match for %s" +#define TXT_DEATH9 TXT(8) //"%s wishes he was as good as %s" +#define TXT_DEATH10 TXT(9) //"%s got messed up by %s" +#define TXT_SUICIDE1 TXT(10) //"%s blasts himself" +#define TXT_SUICIDE2 TXT(11) //"%s Bursts his own bubble" +#define TXT_SUICIDE3 TXT(12) //"%s doesn't know his own strength" +#define TXT_SUICIDE4 TXT(13) //"No prize for %s" +#define TXT_SUICIDE5 TXT(14) //"%s doesn't wish to live anymore" +#define TXT_SUICIDE6 TXT(15) //"%s SUCKS!" +#define TXT_TEAMSCORE TXT(16) //"%s Team Scores %d Points [%d]" +#define TXT_PICKUPFLAGSPEW TXT(17) //"%s (%s) finds the %s Flag among some debris!" +#define TXT_PICKUPFLAG TXT(18) //"%s (%s) picks up the %s flag" +#define TXT_STATS TXT(19) //"Stats" +#define TXT_TEAMSCOREFORM TXT(20) //"%s Team %d[%d]" +#define TXT_TEAMFORM TXT(21) //"%s Team" +#define TXT_WELCOME TXT(22) //"Welcome to Capture The Flag %s!" +#define TXT_JOINED TXT(23) //"%s has joined CTF" +#define TXT_PILOT TXT(24) //"Pilot" +#define TXT_KILLS TXT(25) //"Kills" +#define TXT_DEATHS TXT(26) //"Deaths" +#define TXT_SUICIDES TXT(27) //"Suicides" +#define TXT_POINTS TXT(28) //"Points" +#define TXT_CTF TXT(29) //"Capture The Flag" +#define TXT_PING TXT(30) //"Ping" +#define TXT_HATTRICK TXT(31) //"%s has achieved a Hat Trick!!!" +#define TXT_HATTRICKFIRST TXT(32) //"%s is the first to get a Hat Trick!!!" +#define TXT_CAPTURE TXT(33) //"%s (%s) captures the %s Flag!" +#define TXT_CAPTURETWO TXT(34) //"%s (%s) captures the %s and %s Flags!" +#define TXT_CAPTURETHREE TXT(35) //"%s (%s) captures the %s, %s and %s Flags!" +#define TXT_RETURN TXT(36) //"%s (%s) returns the %s Flag!" +#define TXT_STAT_HEADING TXT(37) //"Capture The Flag\r\nGame: %s\r\nLevel: %d\r\n" +#define TXT_STAT_HEADINGA TXT(38) //"Rank Team Name Score Kills Deaths Suicides Time In Game" +#define TXT_STAT_HEADINGB TXT(39) //"\r\nIndividual Stats\r\n" +#define TXT_STAT_TIG TXT(40) //"Total Time In Game: %s" +#define TXT_STAT_HEADINGC TXT(41) //"Callsign: Kills: Deaths:" +#define TXT_STAT_SAVED TXT(42) //"Stats saved to file" +#define TXT_KILLS_SHORT TXT(43) //"K" +#define TXT_DEATHS_SHORT TXT(44) //"D" +#define TXT_SUICIDES_SHORT TXT(45) //"S" + +#endif \ No newline at end of file diff --git a/ctf/Makefile b/ctf/Makefile new file mode 100644 index 00000000..05c5efd8 --- /dev/null +++ b/ctf/Makefile @@ -0,0 +1,24 @@ +include ../../default.mak + +OBJS = ctf.o +REFS = ctf.cpp +LIBNAME = ../../netgames/ctf.d3m + +CDLFLAGS = $(CFLAGS) -fPIC +LDLFLAGS = -shared -ldl + +all: depall $(OBJS) + gcc $(LDLFLAGS) -o $(LIBNAME) $(OBJS) /usr/lib/dmfc.so + +depall: + $(CC) -E -M $(CFLAGS) $(DEFINES) $(REFS) > .depend + +clean: + rm -f $(OBJS) *~ $(LIBNAME) core + +%.o: %.cpp + $(CC) $(CDLFLAGS) $(DEFINES) -c $< -o $@ + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/ctf/ctf.cpp b/ctf/ctf.cpp new file mode 100644 index 00000000..03efe66a --- /dev/null +++ b/ctf/ctf.cpp @@ -0,0 +1,2834 @@ +/* +* $Logfile: /DescentIII/Main/ctf/ctf.cpp $ +* $Revision: 1.1.1.1 $ +* $Date: 2003-08-26 03:56:47 $ +* $Author: kevinb $ +* +* +* +* $Log: not supported by cvs2svn $ + * + * 140 10/03/01 1:05p Matt + * Made team_name buffer large enough to hold the team number *plus* the + * number of players on the team. + * + * 139 9/24/01 2:28p Matt + * Allowed room for longer team name on results screen. + * + * 138 9/20/01 12:58p Matt + * Added a team member list to the stats file. + * + * 137 10/21/99 9:27p Jeff + * B.A. Macintosh code merge + * + * 136 9/03/99 5:30p Jeff + * use the flag's roomnumber instead of the player's roomnum when checking + * for a score (in case of a really thin room that the flag is in) + * + * 135 8/17/99 5:53p Jeff + * track ranks on PXO + * + * 134 7/15/99 1:17a Jeff + * fixed up $scores + * + * 133 7/13/99 12:10p Jeff + * added some specific text taunt token decoding + * + * 132 7/12/99 2:27p Jeff + * fixed PLR to only display the team label for the disconnected list if + * there are people in the list + * + * 131 7/11/99 6:54p Jeff + * fixed PLR so it doesn't go off the screen on long lists and active + * players in the game are shown first + * + * 130 6/10/99 5:21p Jeff + * fixed crash in french version, due to local array being to small + * + * 129 5/26/99 4:38a Jeff + * fixed ctf bad scoring bugs + * + * 128 5/23/99 3:04a Jason + * fixed bug with player rankings not being updated correctly + * + * 127 5/20/99 7:54p 3dsmax + * changed number of attach points + * + * 126 5/12/99 11:04p Jeff + * dmfc and multiplayer games now have endian friendly packets (*whew*) + * + * 125 5/12/99 11:28a Jeff + * added sourcesafe comment block +* +* $NoKeywords: $ +*/ + + + +#include "gamedll_header.h" +#include + +#include "idmfc.h" +#include "ctf.h" +#include "CTFstr.h" + +IDMFC *DMFCBase; +IDmfcStats *dstat; + +object *dObjects; +player *dPlayers; +room *dRooms; +netplayer *dNetPlayers; + +#define SPID_GAMESTATE 0x01 +#define SPID_ADDDELFLAG 0x02 +#define SPID_COLLIDE 0x03 + +//Inventory flags +#define FLAGMASK_REDTEAM 0x01 +#define FLAGMASK_BLUETEAM 0x02 +#define FLAGMASK_GREENTEAM 0x04 +#define FLAGMASK_YELLOWTEAM 0x08 + +//athome masks +#define REDAH 0x001 +#define BLUEAH 0x002 +#define GREENAH 0x004 +#define YELLOWAH 0x008 + +#define FLAG_TIMEOUT_VALUE 120 +//Sound name defines +#define SOUND_PICKUPFLAG_OWNTEAM "CTFPickupFlag1" +#define SOUND_PICKUPFLAG_OTHERTEAM "CTFPickupFlag1" +#define SOUND_SCORE_OWNTEAM "CTFScore1" +#define SOUND_SCORE_OTHERTEAM "CTFScore1" +#define SOUND_LOSEFLAG_OWNTEAM "CTFLostFlag1" +#define SOUND_LOSEFLAG_OTHERTEAM "CTFLostFlag1" +#define SOUND_FLAGRETURNED_OWNTEAM "CTFReturnedFlag1" +#define SOUND_FLAGRETURNED_OTHERTEAM "CTFReturnedFlag1" +#define SOUND_HATTRICK_FIRST "CTFHatTrick" +#define SOUND_HATTRICK_REGULAR "CTFHatTrick" +/* +$$TABLE_SOUND "CTFPickupFlag1" +$$TABLE_SOUND "CTFPickupFlag1" +$$TABLE_SOUND "CTFScore1" +$$TABLE_SOUND "CTFScore1" +$$TABLE_SOUND "CTFLostFlag1" +$$TABLE_SOUND "CTFLostFlag1" +$$TABLE_SOUND "CTFReturnedFlag1" +$$TABLE_SOUND "CTFReturnedFlag1" +$$TABLE_SOUND "CTFHatTrick" +$$TABLE_SOUND "CTFHatTrick" +*/ +int snd_return_ownteam = -1; +int snd_return_otherteam = -1; +int snd_pickedup_otherteam = -1; +int snd_pickedup_ownteam = -1; +int snd_score_ownteam = -1; +int snd_score_otherteam = -1; +int snd_lose_ownteam = -1; +int snd_lose_otherteam = -1; +int snd_hattrick_first = -1; +int snd_hattrick_reg = -1; + +typedef struct +{ + int Score[2]; +}tPlayerStat; //Overall scores (throughout the game) +int pack_pstat(tPlayerStat *user_info,ubyte *data) +{ + int count = 0; + MultiAddInt(user_info->Score[0],data,&count); + MultiAddInt(user_info->Score[1],data,&count); + return count; +} + +int unpack_pstat(tPlayerStat *user_info,ubyte *data) +{ + int count = 0; + user_info->Score[0] = MultiGetInt(data,&count); + user_info->Score[1] = MultiGetInt(data,&count); + return count; +} + +int SortedPlayers[MAX_PLAYER_RECORDS]; //sorted player nums +int SortedPLRPlayers[DLLMAX_TEAMS][MAX_PLAYER_RECORDS]; + +int TeamScores[DLLMAX_TEAMS]; //teams scores +int OverallTeamScores[DLLMAX_TEAMS]; //overall scores per team +int SortedTeams[DLLMAX_TEAMS]; //sorted team scores +int Highlight_bmp = -1; +bool DisplayScoreScreen; +bool Someone_has_hattrick = false; //this is false if no one has had a hattrick this level +bool First_game_frame = false; + +int FlagIDs[DLLMAX_TEAMS]; //Flag Object ID's +int AFlagIDs[DLLMAX_TEAMS]; //Attached Flag Object ID's +int GoalRooms[DLLMAX_TEAMS]; //Goal Rooms for Teams +int FlagBmp[DLLMAX_TEAMS]; //Flag Bitmap handles +int FlagAHBmp[DLLMAX_TEAMS]; //Flag At Home Bitmap handles +int DimFlagAHBmp[DLLMAX_TEAMS]; //Dimmed versions of the Flag At Home Bitmaps +bool FlagAtHome[DLLMAX_TEAMS]; //Flag At Home bools +int HasFlag[DLLMAX_TEAMS]; //List of Playernums of who has what flag, -1 if no one does +bool DisplayFlagBlink=true,DisplayScoreBlink=true; +int WhoJustFlagged=-1,WhoJustFlaggedTimer=-1; +int WhoJustScored=-1,WhoJustScoredTimer=-1; +int CTFNumOfTeams = 2; +int ChildFlags[DLLMAX_TEAMS]; //Object handles of attached flags as a player has em + +float Flag_timeout_timers[DLLMAX_TEAMS]; +bool display_my_welcome = false; + +void OnTimerScoreKill(void); //timer callback: when a score flash timer ends +void OnTimerScore(void); //timer callback: on a score flash interval +void OnTimer(void); //timer callback: when a flag taken flash timer ends +void OnTimerKill(void); //timer callback: on a flag taken flash interval +void DisplayWelcomeMessage(int player_num); //displays a welcome message to the player when he joins +void SortTeamScores(int *sortedindex,int *scores); //sorts an array of team scores, filling in the sorted index numbers +void DisplayHUDScores(struct tHUDItem *hitem); //callback when the HUD info is to be drawn +void ReceiveGameState(ubyte *data); //callback when a gamestate packet is received from the server +void SendGameState(int playernum); //called when the server is to send gamestate packet to a client +void SetColoredBalls(int playernum,bool reset=false);//sets the colored balls around a player (determined by what is in their inventory) +void ChangeNumberOfTeams(int newsize); //called when the number of teams in the game is changed or to be changed +void DoFlagReturnedHome(int team); //called to handle any events when a flag is returned home for a team +void DoLoseFlag(int team); //called to handle any events when a team loses their flag +void TellClientsToAddorDelFlag(int pnum,int team,int objnum,bool add); +void ServerIsTellingMeToAddorDelAFlag(ubyte *data); +void OnGetTokenString(char *src,char *dest,int dest_size); +// returns the number of flags a player has, 0 if none, or an invalid pnum +int GetFlagCountForPlayer(int pnum); +// returns the mask of which flags this player currently has +ubyte GetFlagMaskForPlayer(int pnum); +// adds a flag to a player, as a precaution, it will go through all the players and makes sure that no one +// has the flag that is being added. If they are adding the flag, than remove that flag from whoever we thought had it +// it will return false if it had to remove a flag from a player +bool GivePlayerFlag(int pnum,ubyte team); +//this function takes a flag away from the player, useful for when he scores, spews, disconnects, or observer modes +void LoseFlagForPlayer(int pnum,ubyte team,bool remove_from_inven=true); + +/////////////////////////////////////////////// +//localization info/functions +char **StringTable; +int StringTableSize = 0; +char *_ErrorString = "Missing String"; +char *GetString(int d){if( (d<0) || (d>=StringTableSize) ) return _ErrorString; else return StringTable[d];} +void SaveStatsToFile(char *filename); + +#ifdef MACINTOSH +#pragma export on +#endif + +// This function gets called by the game when it wants to learn some info about the game +void DLLFUNCCALL DLLGetGameInfo (tDLLOptions *options) +{ + options->flags = DOF_MAXTEAMS|DOF_MINTEAMS; + options->max_teams = 4; + options->min_teams = 2; + strcpy(options->game_name,TXT_CTF); + strcpy(options->requirements,"MINGOALS2,GOALPERTEAM"); +} + +void DetermineScore(int precord_num,int column_num,char *buffer,int buffer_size) +{ + player_record *pr = DMFCBase->GetPlayerRecord(precord_num); + if(!pr || pr->state==STATE_EMPTY){ + buffer[0] = '\0'; + return; + } + + tPlayerStat *stat = (tPlayerStat *)pr->user_info; + sprintf(buffer,"%d",(stat)?stat->Score[DSTAT_LEVEL]:0); +} + +void TeamScoreCallback(int team,char *buffer,int buffer_size) +{ + ASSERT(team>=0 && teamGetPlayerRecord(precord_num); + int flagcount,flagmask; + + if(pr && pr->state==STATE_INGAME ){ + + flagcount = GetFlagCountForPlayer(pr->pnum); + + if(!flagcount) + return; + + flagmask = GetFlagMaskForPlayer(pr->pnum); + + //Display the flags that this player has + x = x + w - (11*flagcount); + for(int q=0;q>1; + } + } +} + + +/////////////////////////////////////////////// +// Initializes the game function pointers +void DLLFUNCCALL DLLGameInit(int *api_func,ubyte *all_ok,int num_teams_to_use) +{ + *all_ok = 1; + DMFCBase = CreateDMFC(); + if(!DMFCBase) + { + *all_ok = 0; + return; + } + + dstat = CreateDmfcStats(); + if(!dstat) + { + *all_ok = 0; + return; + } + + DMFCBase->LoadFunctions(api_func); + + // Setup event handlers + DMFCBase->Set_OnInterval(OnInterval); + DMFCBase->Set_OnHUDInterval(OnHUDInterval); + DMFCBase->Set_OnKeypress(OnKeypress); + DMFCBase->Set_OnServerGameCreated(OnServerGameCreated); + DMFCBase->Set_OnClientLevelStart(OnClientLevelStart); + DMFCBase->Set_OnClientLevelEnd(OnClientLevelEnd); + DMFCBase->Set_OnGameStateRequest(OnGameStateRequest); + DMFCBase->Set_OnPlayerConnect(OnPlayerConnect); + DMFCBase->Set_OnClientPlayerKilled(OnClientPlayerKilled); + DMFCBase->Set_OnServerCollide(OnServerCollide); + //DMFCBase->Set_OnClientCollide(OnClientCollide); + DMFCBase->Set_OnPLRInterval(OnPLRInterval); + DMFCBase->Set_OnPLRInit(OnPLRInit); + DMFCBase->Set_OnCanChangeTeam(OnCanChangeTeam); + DMFCBase->Set_OnSaveStatsToFile(OnSaveStatsToFile); + DMFCBase->Set_OnLevelEndSaveStatsToFile(OnLevelEndSaveStatsToFile); + DMFCBase->Set_OnDisconnectSaveStatsToFile(OnDisconnectSaveStatsToFile); + DMFCBase->Set_OnPrintScores(OnPrintScores); + DMFCBase->Set_OnPlayerEntersObserver(OnPlayerEntersObserver); + DMFCBase->Set_OnClientPlayerDisconnect(OnClientPlayerDisconnect); + DMFCBase->Set_OnPlayerChangeTeam(OnPlayerChangeTeam); + DMFCBase->Set_OnGetTokenString(OnGetTokenString); + + // Setup arrays for easier to read code + dObjects = DMFCBase->GetObjects(); + dPlayers = DMFCBase->GetPlayers(); + dRooms = DMFCBase->GetRooms(); + dNetPlayers = DMFCBase->GetNetPlayers(); + + netgame_info *Netgame = DMFCBase->GetNetgameInfo(); + Netgame->flags |= (NF_TRACK_RANK); + + CTFNumOfTeams = num_teams_to_use; + + DMFCBase->GameInit(CTFNumOfTeams); + DLLCreateStringTable("CTF.str",&StringTable,&StringTableSize); + DLLmprintf((0,"%d strings loaded from string table\n",StringTableSize)); + if(!StringTableSize){ + *all_ok = 0; + return; + } + + ChangeNumberOfTeams(CTFNumOfTeams); + + //add the death and suicide messages + DMFCBase->AddDeathMessage(TXT_DEATH1,true); + DMFCBase->AddDeathMessage(TXT_DEATH2,true); + DMFCBase->AddDeathMessage(TXT_DEATH3,false); + DMFCBase->AddDeathMessage(TXT_DEATH4,false); + DMFCBase->AddDeathMessage(TXT_DEATH5,true); + DMFCBase->AddDeathMessage(TXT_DEATH6,true); + DMFCBase->AddDeathMessage(TXT_DEATH7,false); + DMFCBase->AddDeathMessage(TXT_DEATH8,true); + DMFCBase->AddDeathMessage(TXT_DEATH9,true); + DMFCBase->AddDeathMessage(TXT_DEATH10,true); + + DMFCBase->AddSuicideMessage(TXT_SUICIDE1); + DMFCBase->AddSuicideMessage(TXT_SUICIDE2); + DMFCBase->AddSuicideMessage(TXT_SUICIDE3); + DMFCBase->AddSuicideMessage(TXT_SUICIDE4); + DMFCBase->AddSuicideMessage(TXT_SUICIDE5); + DMFCBase->AddSuicideMessage(TXT_SUICIDE6); + + //setup the Playerstats struct so DMFC can handle it automatically when a new player enters the game + DMFCBase->SetupPlayerRecord(sizeof(tPlayerStat),(int (*)(void *,ubyte *))pack_pstat,(int (*)(void *,ubyte *))unpack_pstat); + + DMFCBase->AddHUDItemCallback(HI_TEXT,DisplayHUDScores); + + DMFCBase->RegisterPacketReceiver(SPID_GAMESTATE,ReceiveGameState); + DMFCBase->RegisterPacketReceiver(SPID_ADDDELFLAG,ServerIsTellingMeToAddorDelAFlag); + DMFCBase->RegisterPacketReceiver(SPID_COLLIDE,OnClientCollide); + + //Load all the bitmaps + FlagBmp[RED_TEAM] = DLLbm_AllocLoadFileBitmap("RedFlagIcon.ogf",0); + FlagBmp[BLUE_TEAM] = DLLbm_AllocLoadFileBitmap("BlueFlagIcon.ogf",0); + FlagBmp[GREEN_TEAM] = DLLbm_AllocLoadFileBitmap("GreenFlagIcon.ogf",0); + FlagBmp[YELLOW_TEAM] = DLLbm_AllocLoadFileBitmap("YellowFlagIcon.ogf",0); + //athome bitmaps + FlagAHBmp[RED_TEAM] = DLLbm_AllocLoadFileBitmap("RedFlagIcon.ogf",0); + FlagAHBmp[BLUE_TEAM] = DLLbm_AllocLoadFileBitmap("BlueFlagIcon.ogf",0); + FlagAHBmp[GREEN_TEAM] = DLLbm_AllocLoadFileBitmap("GreenFlagIcon.ogf",0); + FlagAHBmp[YELLOW_TEAM] = DLLbm_AllocLoadFileBitmap("YellowFlagIcon.ogf",0); + DimFlagAHBmp[RED_TEAM] = DLLbm_AllocLoadFileBitmap("RedFlagIconDim.ogf",0); + DimFlagAHBmp[BLUE_TEAM] = DLLbm_AllocLoadFileBitmap("BlueFlagIconDim.ogf",0); + DimFlagAHBmp[GREEN_TEAM] = DLLbm_AllocLoadFileBitmap("GreenFlagIconDim.ogf",0); + DimFlagAHBmp[YELLOW_TEAM] = DLLbm_AllocLoadFileBitmap("YellowFlagIconDim.ogf",0); + //fill in the IDs + + + FlagIDs[RED_TEAM] = DLLFindObjectIDName("FlagRed"); + FlagIDs[BLUE_TEAM] = DLLFindObjectIDName("Flagblue"); + FlagIDs[GREEN_TEAM] = DLLFindObjectIDName("FlagGreen"); + FlagIDs[YELLOW_TEAM] = DLLFindObjectIDName("FlagYellow"); + AFlagIDs[RED_TEAM] = DLLFindObjectIDName("ShipRedFlag"); + AFlagIDs[BLUE_TEAM] = DLLFindObjectIDName("ShipBlueFlag"); + AFlagIDs[GREEN_TEAM] = DLLFindObjectIDName("ShipGreenFlag"); + AFlagIDs[YELLOW_TEAM] = DLLFindObjectIDName("ShipYellowFlag"); + + //give initial values for the at home so they're set + FlagAtHome[RED_TEAM] = FlagAtHome[BLUE_TEAM] = + FlagAtHome[GREEN_TEAM] = FlagAtHome[YELLOW_TEAM] = false; + + //make sure all was init ok + for(int i=0;iBAD_BITMAP_HANDLE){ + ushort *data = DLLbm_data(Highlight_bmp,0); + if(!data){ + //bail on out of here + *all_ok = 0; + return; + } + for(int x=0;x<32*32;x++){ + data[x] = GR_RGB16(50,50,50)|OPAQUE_FLAG; + } + } + + //Load in and touch all the sounds so they're ready to rock + snd_score_ownteam = DLLFindSoundName(IGNORE_TABLE(SOUND_SCORE_OWNTEAM)); + if(snd_score_ownteam!=-1) + DLLTouchSound(snd_score_ownteam); + snd_score_otherteam = DLLFindSoundName(IGNORE_TABLE(SOUND_SCORE_OTHERTEAM)); + if(snd_score_otherteam!=-1) + DLLTouchSound(snd_score_otherteam); + snd_pickedup_otherteam =DLLFindSoundName(IGNORE_TABLE(SOUND_PICKUPFLAG_OWNTEAM)); + if(snd_pickedup_otherteam!=-1) + DLLTouchSound(snd_pickedup_otherteam); + snd_pickedup_ownteam =DLLFindSoundName(IGNORE_TABLE(SOUND_PICKUPFLAG_OTHERTEAM)); + if(snd_pickedup_ownteam!=-1) + DLLTouchSound(snd_pickedup_ownteam); + snd_return_ownteam = DLLFindSoundName(IGNORE_TABLE(SOUND_FLAGRETURNED_OWNTEAM)); + if(snd_return_ownteam!=-1) + DLLTouchSound(snd_return_ownteam); + snd_return_otherteam = DLLFindSoundName(IGNORE_TABLE(SOUND_FLAGRETURNED_OTHERTEAM)); + if(snd_return_otherteam!=-1) + DLLTouchSound(snd_return_otherteam); + snd_lose_ownteam = DLLFindSoundName(IGNORE_TABLE(SOUND_LOSEFLAG_OWNTEAM)); + if(snd_lose_ownteam!=-1) + DLLTouchSound(snd_lose_ownteam); + snd_lose_otherteam = DLLFindSoundName(IGNORE_TABLE(SOUND_LOSEFLAG_OTHERTEAM)); + if(snd_lose_otherteam!=-1) + DLLTouchSound(snd_lose_otherteam); + snd_hattrick_first = DLLFindSoundName(IGNORE_TABLE(SOUND_HATTRICK_FIRST)); + if(snd_hattrick_first!=-1) + DLLTouchSound(snd_hattrick_first); + snd_hattrick_reg = DLLFindSoundName(IGNORE_TABLE(SOUND_HATTRICK_REGULAR)); + if(snd_hattrick_reg!=-1) + DLLTouchSound(snd_hattrick_reg); + + DisplayScoreScreen = false; + + + // Initialize the Stats Manager + // ---------------------------- + + tDmfcStatsInit tsi; + tDmfcStatsColumnInfo pl_col[7]; + char gname[32]; + strcpy(gname,TXT_CTF); + + tsi.flags = DSIF_SHOW_PIC|DSIF_SHOW_OBSERVERICON|DSIF_SEPERATE_BY_TEAM; + tsi.cColumnCountDetailed = 0; + tsi.cColumnCountPlayerList = 7; + tsi.clbDetailedColumnBMP = NULL; + tsi.clbDetailedColumn = NULL; + tsi.clbPlayerColumn = DetermineScore; + tsi.clbPlayerColumnBMP = ShowStatBitmap; + tsi.DetailedColumns = NULL; + tsi.GameName = gname; + tsi.MaxNumberDisplayed = NULL; + tsi.PlayerListColumns = pl_col; + tsi.SortedPlayerRecords = SortedPlayers; + tsi.clTeamLine = TeamScoreCallback; + + pl_col[0].color_type = DSCOLOR_TEAM; + pl_col[0].title[0] = '\0'; + pl_col[0].type = DSCOL_BMP; + pl_col[0].width = 33; + + pl_col[1].color_type = DSCOLOR_TEAM; + strcpy(pl_col[1].title,TXT_PILOT); + pl_col[1].type = DSCOL_PILOT_NAME; + pl_col[1].width = 120; + + pl_col[2].color_type = DSCOLOR_TEAM; + strcpy(pl_col[2].title,TXT_POINTS); + pl_col[2].type = DSCOL_CUSTOM; + pl_col[2].width = 52; + + pl_col[3].color_type = DSCOLOR_TEAM; + strcpy(pl_col[3].title,TXT_KILLS_SHORT); + pl_col[3].type = DSCOL_KILLS_LEVEL; + pl_col[3].width = 47; + + pl_col[4].color_type = DSCOLOR_TEAM; + strcpy(pl_col[4].title,TXT_DEATHS_SHORT); + pl_col[4].type = DSCOL_DEATHS_LEVEL; + pl_col[4].width = 47; + + pl_col[5].color_type = DSCOLOR_TEAM; + strcpy(pl_col[5].title,TXT_SUICIDES_SHORT); + pl_col[5].type = DSCOL_SUICIDES_LEVEL; + pl_col[5].width = 47; + + pl_col[6].color_type = DSCOLOR_TEAM; + strcpy(pl_col[6].title,TXT_PING); + pl_col[6].type = DSCOL_PING; + pl_col[6].width = 40; + + dstat->Initialize(&tsi); +} +// Called when the DLL is shutdown +void DLLFUNCCALL DLLGameClose () +{ + //@@SaveConfig(); + //@@DMFCBase->CFGClose(); + + //Free all the bitmaps + DLLbm_FreeBitmap(FlagBmp[RED_TEAM]); + DLLbm_FreeBitmap(FlagBmp[BLUE_TEAM]); + DLLbm_FreeBitmap(FlagBmp[GREEN_TEAM]); + DLLbm_FreeBitmap(FlagBmp[YELLOW_TEAM]); + DLLbm_FreeBitmap(DimFlagAHBmp[RED_TEAM]); + DLLbm_FreeBitmap(DimFlagAHBmp[BLUE_TEAM]); + DLLbm_FreeBitmap(DimFlagAHBmp[GREEN_TEAM]); + DLLbm_FreeBitmap(DimFlagAHBmp[YELLOW_TEAM]); + DLLbm_FreeBitmap(FlagAHBmp[RED_TEAM]); + DLLbm_FreeBitmap(FlagAHBmp[BLUE_TEAM]); + DLLbm_FreeBitmap(FlagAHBmp[GREEN_TEAM]); + DLLbm_FreeBitmap(FlagAHBmp[YELLOW_TEAM]); + + if(Highlight_bmp>BAD_BITMAP_HANDLE) + DLLbm_FreeBitmap(Highlight_bmp); + + DLLDestroyStringTable(StringTable,StringTableSize); + + if(dstat) + { + dstat->DestroyPointer(); + dstat = NULL; + } + + if(DMFCBase) + { + DMFCBase->GameClose(); + DMFCBase->DestroyPointer(); + DMFCBase = NULL; + } +} + +///////////////////////////////////////////////////////////// +//DMFC Overrides + +//OnHUDInterval +void OnHUDInterval(void) +{ + dstat->DoFrame(); + + DMFCBase->DisplayOutrageLogo(); + + DMFCBase->OnHUDInterval(); +} + +//OnInterval +void OnInterval(void) +{ + DMFCBase->GetSortedPlayerSlots(SortedPlayers,MAX_PLAYER_RECORDS); + + SortTeamScores(SortedTeams,TeamScores); + + //Determine if a flag has timed out yet + for(int i=0;iGetGametime()>=Flag_timeout_timers[i]){ + //the timeout has expired, move home! + vector home_pos; + int home,objnum; + + Flag_timeout_timers[i] = 0; + FlagAtHome[i] = true; + HasFlag[i] = -1; + home = GoalRooms[i]; + objnum = -1; + + //find the flag objnum + for(int o=0;oGetLocalRole()==LR_SERVER){ + int flagid = FlagIDs[i]; + if( (flagid!=-1) && (home>=0) && (home<=DMFCBase->GetHighestRoomIndex()) && (!ROOMNUM_OUTSIDE(home)) && (dRooms[home].used) ){ + //Safe to create the flag + DLLComputeRoomCenter(&home_pos,&dRooms[home]); + objnum = DLLObjCreate(OBJ_POWERUP,flagid,home,&home_pos,NULL); + DLLMultiSendObject(&dObjects[objnum],0); + } + } + }else{ + if( (home>=0) && (home<=DMFCBase->GetHighestRoomIndex()) && (!ROOMNUM_OUTSIDE(home)) && (dRooms[home].used) ){ + DLLComputeRoomCenter(&home_pos,&dRooms[home]); + DLLObjSetPos(&dObjects[objnum],&home_pos,home,NULL,false); + } + } + } + } + } + + DMFCBase->OnInterval(); + + First_game_frame = true; +} + +//OnKeypress +// What it needs to do: +// 1) Test for F7 keypress +void OnKeypress(int key) +{ + dllinfo *Data; + Data = DMFCBase->GetDLLInfoCallData(); + + switch(key){ + case K_F7: + DisplayScoreScreen = !DisplayScoreScreen; + DMFCBase->EnableOnScreenMenu(false); + dstat->Enable(DisplayScoreScreen); + break; + case K_PAGEDOWN: + if(DisplayScoreScreen){ + dstat->ScrollDown(); + Data->iRet = 1; + } + break; + case K_PAGEUP: + if(DisplayScoreScreen){ + dstat->ScrollUp(); + Data->iRet = 1; + } + break; + case K_F6: + DisplayScoreScreen = false; + dstat->Enable(false); + break; + case K_ESC: + if(DisplayScoreScreen){ + dstat->Enable(false); + DisplayScoreScreen = false; + Data->iRet = 1; + } + break; + } + + DMFCBase->OnKeypress(key); +} + +//OnServerGameCreated +// What it needs to do: +// 1) Zero out all the stats for every player +// 2) Zero out team scores +// 3) Display welcome message to server +void OnServerGameCreated(void) +{ + DMFCBase->OnServerGameCreated(); + tPlayerStat *stat; + player_record *pr; + int i; + + for(i=0;iGetPlayerRecord(i); + if(pr){ + stat = (tPlayerStat *)pr->user_info; + if(stat){ + stat->Score[DSTAT_LEVEL] = 0; + stat->Score[DSTAT_OVERALL] = 0; + } + } + } + for(i=0;iOnClientLevelStart(); + + First_game_frame = false; + + for(i=0;iGetPlayerRecord(i); + if(pr){ + stat = (tPlayerStat *)pr->user_info; + if(stat){ + stat->Score[DSTAT_LEVEL] = 0; + } + } + } + for(i=0;iSetNumberOfTeams(CTFNumOfTeams); + DLLMultiPaintGoalRooms(NULL); + + //Bash the inventory since it doesn't get reset for the server + DLLInvReset(DMFCBase->GetPlayerNum()); + + //Display our welcome message + display_my_welcome = true; + + //If we are the server create the flags + if(DMFCBase->GetLocalRole()!=LR_SERVER){ + //Get the game state + DMFCBase->RequestGameState(); + return; + } + + vector vpos; + int objnum; + int flagid,goalroom; + + for(i=0;i=0) && (goalroom<=DMFCBase->GetHighestRoomIndex()) && (!ROOMNUM_OUTSIDE(goalroom)) && (dRooms[goalroom].used) ){ + //Safe to create the flag + DLLmprintf((0,"Creating %s Flag\n",DMFCBase->GetTeamString(i))); + DLLComputeRoomCenter(&vpos,&dRooms[goalroom]); + objnum = DLLObjCreate(OBJ_POWERUP,flagid,goalroom,&vpos,NULL); + DLLMultiSendObject(&dObjects[objnum],0); + } + } +} + +//OnServerCollide +// What it needs to do: +// 1) See if the player has collided with a flag, if so pass to clients +void OnServerCollide(object *me_obj,object *it_obj) +{ + //see if we need to send this event to the clients + //only if me==player it==flag powerup + if(!me_obj || !it_obj) + return; + if( (me_obj->type==OBJ_PLAYER||me_obj->type==OBJ_GHOST) && (it_obj->type==OBJ_POWERUP) ) + if( (it_obj->id==FlagIDs[RED_TEAM]) || + (it_obj->id==FlagIDs[BLUE_TEAM]) || + (it_obj->id==FlagIDs[GREEN_TEAM]) || + (it_obj->id==FlagIDs[YELLOW_TEAM]) ){ + + //Start a packet for the collide + ubyte data[MAX_GAME_DATA_SIZE]; + int count = 0; + DMFCBase->StartPacket(data,SPID_COLLIDE,&count); + int start = count; + + //we need me, it and me roomnum + MultiAddUshort((me_obj-dObjects),data,&count); + MultiAddUshort((it_obj-dObjects),data,&count); + MultiAddInt(it_obj->roomnum,data,&count); + + DMFCBase->SendPacket(data,count,SP_ALL); + OnClientCollide(&data[start]); + } +} + +//OnClientCollide +// What it needs to do: +// 1) See if Player collided with own flag +// 1.1) Check to see if in home goal +// 1.1.1) Reset colored balls +// 1.1.2) Remove all the flags from the inventory, send them back to their home goal +// 1.1.3) Add scores +// 1.1.4) Print out score +// 1.1.5) Do Kill Goal check +// 1,2) Move home flag to center of base +// 2) else collide with another team's flag +// 2.1) Add flag to inventory +// 2.2) Set rotating balls +// 2.3) Print out message +void OnClientCollide(ubyte *data) +{ + object *me_obj,*it_obj; + int me_roomnum; + int count = 0; + int me_serv_objnum,it_serv_objnum,me_client_objnum,it_client_objnum; + + me_serv_objnum = MultiGetUshort(data,&count); + it_serv_objnum = MultiGetUshort(data,&count); + me_roomnum = MultiGetInt(data,&count); + + me_client_objnum = DMFCBase->ConvertServerToLocalObjnum(me_serv_objnum); + it_client_objnum = DMFCBase->ConvertServerToLocalObjnum(it_serv_objnum); + + if(me_client_objnum==-1 || it_client_objnum==-1) + { + Int3(); + return; + } + + me_obj = &dObjects[me_client_objnum]; + it_obj = &dObjects[it_client_objnum]; + + // now process the collide + + int fteam=-1; //flags team + int pnum = me_obj->id; //player number + int pteam=DMFCBase->GetPlayerTeam(pnum); //player's team + int i; + bool play_return_home_msg = false; + + for(i=0;iid==FlagIDs[i]) + fteam = i; + } + + if(fteam==-1){ + return; //something wrong, as none of the IDs are one of the flag's IDs + } + + // Reset the timer for this flag since it's guaranteed someone owns it now + // or it has been sent home. + Flag_timeout_timers[fteam] = 0; + + //Did player collide with his own team's flag? + if(fteam==pteam) + { + short flag_count = 0; + vector fpos; + int groom; + int flagcount; + int flagmask; + + bool captured_flags[DLLMAX_TEAMS]; + for(int i=0;i=0) && (groom<=DMFCBase->GetHighestRoomIndex()) && (!ROOMNUM_OUTSIDE(groom)) && (dRooms[groom].used)){ + //the room is valid, so move it back to home + + LoseFlagForPlayer(pnum,i); + + if(DMFCBase->GetLocalRole()==LR_SERVER){ + //if we are the server create the object and send it on it's way to the player's + DLLComputeRoomCenter(&fpos,&dRooms[groom]); + int objnum = DLLObjCreate(OBJ_POWERUP,FlagIDs[i],groom,&fpos,NULL); + DLLMultiSendObject(&dObjects[objnum],1); + }//end server create + }//end room ok + + //set it's at home flag + FlagAtHome[i] = true; + }//end flag check + //rotate the flagmask over one to check for the next flag + flagmask = flagmask >> 1; + }//end for loop + + //remove any rotating balls + SetColoredBalls(pnum,true); + + //Now handle any scoring + int score = 0; + switch(flagcount) + { + case 0: + break; + case 1: + score = 1; + break; + case 2: + score = 3; + break; + case 3: + score = 9; + break; + } + + //print out the message and add to the scores + + if(score) + { + tPlayerStat *stat = (tPlayerStat *)DMFCBase->GetPlayerRecordData(pnum); + if(stat){ + stat->Score[DSTAT_LEVEL] +=score; + stat->Score[DSTAT_OVERALL] +=score; + + if(stat->Score[DSTAT_LEVEL]==3){ + if(Someone_has_hattrick){ + DLLAddHUDMessage(TXT_HATTRICK,dPlayers[pnum].callsign); + if(snd_hattrick_reg!=-1) + DLLPlay2dSound(snd_hattrick_reg); + }else{ + DLLAddHUDMessage(TXT_HATTRICKFIRST,dPlayers[pnum].callsign); + if(snd_hattrick_first!=-1) + DLLPlay2dSound(snd_hattrick_first); + Someone_has_hattrick = true; + } + } + } + + TeamScores[pteam]+=score; + OverallTeamScores[pteam]+=score; + int newscore=TeamScores[pteam]; + + switch(flagcount){ + case 1: + { + char t[20]; + t[0] = '\0'; + for(int c=0;cGetTeamString(c)); + break; + } + } + DLLAddHUDMessage(TXT_CAPTURE,dPlayers[pnum].callsign,DMFCBase->GetTeamString(pteam),t); + }break; + case 2: + { + char t[2][20]; + t[0][0] = '\0'; + t[1][0] = '\0'; + int index = 0; + for(int c=0;cGetTeamString(c)); + index++; + if(index==2) + break; + } + } + DLLAddHUDMessage(TXT_CAPTURETWO,dPlayers[pnum].callsign, + DMFCBase->GetTeamString(pteam),t[0],t[1]); + }break; + case 3: + { + char t[3][20]; + t[0][0] = '\0'; + t[1][0] = '\0'; + t[2][0] = '\0'; + + int index = 0; + for(int c=0;cGetTeamString(c)); + index++; + if(index==3) + break; + } + } + DLLAddHUDMessage(TXT_CAPTURETHREE,dPlayers[pnum].callsign, + DMFCBase->GetTeamString(pteam),t[0],t[1],t[2]); + } + } + + if(dPlayers[DMFCBase->GetPlayerNum()].team==pteam){ + if(snd_score_ownteam!=-1) + DLLPlay2dSound(snd_score_ownteam); + }else{ + if(snd_score_otherteam!=-1) + DLLPlay2dSound(snd_score_otherteam); + } + + //Set a Timer to display + if(WhoJustScoredTimer!=-1) + DMFCBase->KillTimer(WhoJustScoredTimer); + WhoJustScoredTimer = DMFCBase->SetTimerInterval(OnTimerScore,0.5f,5.0f,OnTimerScoreKill); + WhoJustScored = pteam; + } + //do the killgoal check + int killgoal; + if(DMFCBase->GetScoreLimit(&killgoal)){ + if(TeamScores[pteam]>=killgoal){ + //That's all she wrote for this level + DLLmprintf((0,"OnClientCollide:Kill Goal Reached!\n")); + DMFCBase->EndLevel(); + } + } + }else{ + DoFlagReturnedHome(pteam); + if(DMFCBase->CheckPlayerNum(pnum)){ + char parm1[20],parm2[20]; + strcpy(parm1,DMFCBase->GetTeamString(pteam)); + strcpy(parm2,DMFCBase->GetTeamString(fteam)); + DLLAddHUDMessage(TXT_RETURN,dPlayers[pnum].callsign,parm1,parm2); + } + } + + //since the player collided with his own team's flag we need to move the flag back home + FlagAtHome[pteam] = true; + HasFlag[pteam] = -1; + vector home_pos; + int home = GoalRooms[pteam]; + + if( (home>=0) && (home<=DMFCBase->GetHighestRoomIndex()) && (!ROOMNUM_OUTSIDE(home)) && (dRooms[home].used) ) + { + DLLComputeRoomCenter(&home_pos,&dRooms[home]); + DLLObjSetPos(it_obj,&home_pos,home,NULL,false); + } + + }//end Player Collides with own team's flag + else{ + //The Player collide with another team's flag + FlagAtHome[fteam] = false; + + //add the flag to the player + GivePlayerFlag(pnum,fteam); + + if(dPlayers[DMFCBase->GetPlayerNum()].team==dPlayers[pnum].team){ + if(snd_pickedup_ownteam!=-1) + DLLPlay2dSound(snd_pickedup_ownteam); + }else{ + if(snd_pickedup_otherteam!=-1) + DLLPlay2dSound(snd_pickedup_otherteam); + } + + //Set a Timer to display + if(WhoJustFlaggedTimer!=-1) + DMFCBase->KillTimer(WhoJustFlaggedTimer); + WhoJustFlaggedTimer = DMFCBase->SetTimerInterval(OnTimer,0.5f,5.0f,OnTimerKill); + WhoJustFlagged = fteam; + + char parm1[20],parm2[20]; + strcpy(parm1,DMFCBase->GetTeamString(pteam)); + strcpy(parm2,DMFCBase->GetTeamString(fteam)); + if(dObjects[dPlayers[pnum].objnum].roomnum==GoalRooms[fteam]){ + DLLAddHUDMessage(TXT_PICKUPFLAG,dPlayers[pnum].callsign,parm1,parm2); + }else{ + DLLAddHUDMessage(TXT_PICKUPFLAGSPEW,dPlayers[pnum].callsign,parm1,parm2); + } + + //remove the flag from the world + if(DMFCBase->GetLocalRole()==LR_SERVER){ + //tell the clients to remove this flag + DLLSetObjectDeadFlag(it_obj,true,false); + } + } +} + +//OnGameStateRequest +// 1) Send game state to new player +void OnGameStateRequest(int player_num) +{ + SendGameState(player_num); + DMFCBase->OnGameStateRequest(player_num); +} + +void OnPlayerConnect(int player_num) +{ + DMFCBase->OnPlayerConnect(player_num); + + tPlayerStat *stat; + stat = (tPlayerStat *)DMFCBase->GetPlayerRecordData(player_num); + if(stat){ + stat->Score[DSTAT_LEVEL] = 0; + stat->Score[DSTAT_OVERALL] = 0; + } + + if(player_num!=DMFCBase->GetPlayerNum()) + { + //announce the arrival of the player + DisplayWelcomeMessage(player_num); + } +} + +void OnClientLevelEnd(void) +{ + DMFCBase->OnClientLevelEnd(); +} + +void OnPlayerChangeTeam(int player_num,int newteam,bool announce,bool spew_onrespawn) +{ + DMFCBase->OnPlayerChangeTeam(player_num,newteam,announce,spew_onrespawn); + player_record *pr = DMFCBase->GetPlayerRecordByPnum(player_num); +} + +//OnClientPlayerKilled +// 1) If suicide add to suicides +// 2) Else add to killer's kill, add to victim's deaths +// 3) Reset colored balls +// 4) If killed in a flag's home goal than put it in the center of the room +void OnClientPlayerKilled(object *killer_obj,int victim_pnum) +{ + int kpnum = -1; + + if(killer_obj){ + if((killer_obj->type==OBJ_PLAYER)||(killer_obj->type==OBJ_GHOST)||(killer_obj->type==OBJ_OBSERVER)) + kpnum = killer_obj->id; + else if(killer_obj->type==OBJ_ROBOT || killer_obj->type == OBJ_BUILDING){ + //countermeasure kill + kpnum = DMFCBase->GetCounterMeasureOwner(killer_obj); + }else{ + kpnum = -1; + } + } + + HandlePlayerSpew(victim_pnum); + DMFCBase->OnClientPlayerKilled(killer_obj,victim_pnum); +} + +void OnClientPlayerDisconnect(int player_num) +{ + HandlePlayerSpew(player_num); + DMFCBase->OnClientPlayerDisconnect(player_num); +} + +void OnPlayerEntersObserver(int pnum,object *piggy) +{ + HandlePlayerSpew(pnum); + DMFCBase->OnPlayerEntersObserver(pnum,piggy); +} + +bool OnCanChangeTeam(int pnum,int newteam) +{ + if(!DMFCBase->OnCanChangeTeam(pnum,newteam)) + return false; + + if(GetFlagCountForPlayer(pnum)){ + DMFCBase->AnnounceTeamChangeDeny(pnum); + return false; + } + + return true; +} + +bool compare_slots(int a,int b) +{ + int ascore,bscore; + player_record *apr,*bpr; + tPlayerStat *astat,*bstat; + + apr = DMFCBase->GetPlayerRecord(a); + bpr = DMFCBase->GetPlayerRecord(b); + if( !apr ) + return true; + if( !bpr ) + return false; + if( apr->state==STATE_EMPTY ) + return true; + if( bpr->state==STATE_EMPTY ) + return false; + astat = (tPlayerStat *)apr->user_info; + bstat = (tPlayerStat *)bpr->user_info; + + if( (apr->state==STATE_INGAME) && (bpr->state==STATE_INGAME) ){ + //both players were in the game + ascore = (astat)?astat->Score[DSTAT_LEVEL]:0; + bscore = (bstat)?bstat->Score[DSTAT_LEVEL]:0; + return (ascorestate==STATE_INGAME) && (bpr->state==STATE_DISCONNECTED) ){ + //apr gets priority since he was in the game on exit + return false; + } + if( (apr->state==STATE_DISCONNECTED) && (bpr->state==STATE_INGAME) ){ + //bpr gets priority since he was in the game on exit + return true; + } + //if we got here then both players were disconnected + ascore = (astat)?astat->Score[DSTAT_LEVEL]:0; + bscore = (bstat)?bstat->Score[DSTAT_LEVEL]:0; + return (ascore=0 && compare_slots(tempsort[j],t); j--){ + tempsort[j+1] = tempsort[j]; + } + // insert + tempsort[j+1] = t; + } + + //copy the array over + memcpy(SortedPlayers,tempsort,MAX_PLAYER_RECORDS*sizeof(int)); + + //Now fill in the final structure of sorted names + int TeamCount[DLLMAX_TEAMS]; + int team; + for(i=0;iGetPlayerRecord(slot); + if(pr && pr->state!=STATE_EMPTY){ + + if(DMFCBase->IsPlayerDedicatedServer(pr)) + continue; //skip dedicated server + + team = (pr->state==STATE_INGAME)?dPlayers[pr->pnum].team:pr->team; + + if(team>=CTFNumOfTeams) + team = 0; + + SortedPLRPlayers[team][TeamCount[team]] = slot; + + TeamCount[team]++; + } + } + for(i=0;iOnPLRInit(); +} + +void OnPLRInterval(void) +{ + DMFCBase->OnPLRInterval(); + + int TeamCol = 35; + int NameCol = 180; + int PointsCol = 320; + int KillsCol = 370; + int DeathsCol = 410; + int SuicidesCol = 450; + int y = 40; + int slot; + bool had_members; + player_record *pr; + tPlayerStat *stat; + + DLLgrtext_SetFont((DMFCBase->GetGameFontTranslateArray())[SMALL_UI_FONT_INDEX]); + + int height = DLLgrfont_GetHeight((DMFCBase->GetGameFontTranslateArray())[SMALL_UI_FONT_INDEX]) + 1; + + //print out header + DLLgrtext_SetColor(GR_RGB(255,255,150)); + DLLgrtext_Printf(PointsCol,y,TXT_POINTS); + DLLgrtext_Printf(NameCol,y,TXT_PILOT); + DLLgrtext_Printf(KillsCol,y,TXT_KILLS_SHORT); + DLLgrtext_Printf(DeathsCol,y,TXT_DEATHS_SHORT); + DLLgrtext_Printf(SuicidesCol,y,TXT_SUICIDES_SHORT); + y+=height; + + bool doing_connected = true; + +do_disconnected_folk: + + for(int team=0;teamWasPlayerInGameAtLevelEnd(SortedPLRPlayers[team][temp_idx]); + if(pnum==-1) + { + show_team_label = true; + break; + } + temp_idx++; + } + }else + { + show_team_label = true; + } + + if(show_team_label){ + //is there anyone on this team? + DLLgrtext_SetColor(DMFCBase->GetTeamColor(team)); + DLLgrtext_Printf(TeamCol,y,TXT_TEAMSCOREFORM,DMFCBase->GetTeamString(team),TeamScores[team],OverallTeamScores[team]); + } + had_members = false; + + for(int index=0;indexGetPlayerRecord(slot); + if(!pr || pr->state==STATE_EMPTY) + continue; + + if(DMFCBase->IsPlayerDedicatedServer(pr)) + continue; + + if( (doing_connected && DMFCBase->WasPlayerInGameAtLevelEnd(slot)==-1) || + (!doing_connected && DMFCBase->WasPlayerInGameAtLevelEnd(slot)!=-1) ) + continue;//we're not handling them right now + + stat = (tPlayerStat *)pr->user_info; + + int pnum=DMFCBase->WasPlayerInGameAtLevelEnd(slot); + if(pnum!=-1) + { + DLLgrtext_SetColor(DMFCBase->GetTeamColor(team)); + }else + { + DLLgrtext_SetColor(GR_RGB(128,128,128)); + } + + //valid player + char temp[120]; + sprintf(temp,"%s",pr->callsign); + DMFCBase->ClipString(PointsCol - NameCol - 10,temp,true); + + DLLgrtext_Printf(NameCol,y,"%s",temp); + DLLgrtext_Printf(PointsCol,y,"%d",(stat)?stat->Score[DSTAT_LEVEL]:0); + DLLgrtext_Printf(KillsCol,y,"%d",pr->dstats.kills[DSTAT_LEVEL]); + DLLgrtext_Printf(DeathsCol,y,"%d",pr->dstats.deaths[DSTAT_LEVEL]); + DLLgrtext_Printf(SuicidesCol,y,"%d",pr->dstats.suicides[DSTAT_LEVEL]); + y+=height; + + if(y>=440) + goto quick_exit; + + had_members = true; + + }//end for + + if(!had_members) + { + //skip a line + y+=height; + + if(y>=440) + goto quick_exit; + } + //on to the next team + }//end for + + if(doing_connected) + { + doing_connected = false; + goto do_disconnected_folk; + } + +quick_exit:; + +} + +void SaveStatsToFile(char *filename) +{ + CFILE *file; + DLLOpenCFILE(&file,filename,"wt"); + if(!file){ + DLLmprintf((0,"Unable to open output file\n")); + return; + } + + //write out game stats + #define BUFSIZE 150 + char buffer[BUFSIZE]; + char tempbuffer[25]; + int sortedslots[MAX_PLAYER_RECORDS]; + player_record *pr,*dpr; + tPInfoStat stat; + tPlayerStat *ps; + int count,length,p; + int team; + + //sort the stats + DMFCBase->GetSortedPlayerSlots(sortedslots,MAX_PLAYER_RECORDS); + + int i,t,j; + + for(i=0;i=0 && compare_slots(sortedslots[j],t); j--){ + sortedslots[j+1] = sortedslots[j]; + } + // insert + sortedslots[j+1] = t; + } + + count = 1; + + sprintf(buffer,TXT_STAT_HEADING,(DMFCBase->GetNetgameInfo())->name,(DMFCBase->GetCurrentMission())->cur_level); + DLLcf_WriteString(file,buffer); + + for(i=0;iGetNumTeams();i++){ + int team = SortedTeams[i]; + + sprintf(buffer,"%s: %d[%d]",DMFCBase->GetTeamString(team),TeamScores[team],OverallTeamScores[team]); + DLLcf_WriteString(file,buffer); + } + strcpy(buffer,"\r\n"); + DLLcf_WriteString(file,buffer); + + //Write team members + DLLcf_WriteString(file,""); //blank line + for(t=0;tGetNumTeams();t++){ + int team_i = SortedTeams[t]; + + sprintf(buffer,"%s:",DMFCBase->GetTeamString(team_i)); + DLLcf_WriteString(file,buffer); + + for(p=0;pGetPlayerRecord(sortedslots[p]); + if( pr && pr->state!=STATE_EMPTY) { + + if(DMFCBase->IsPlayerDedicatedServer(pr)) + continue;//skip dedicated server + + if (pr->team == team_i) { //Check if current team + sprintf(buffer," %s",pr->callsign); + DLLcf_WriteString(file,buffer); + } + } + } + } + DLLcf_WriteString(file,""); //blank line + + sprintf(buffer,TXT_STAT_HEADINGA); + DLLcf_WriteString(file,buffer); + sprintf(buffer,"--------------------------------------------------------------------------------------------------"); + DLLcf_WriteString(file,buffer); + + for(int pslot=0;pslotGetPlayerRecord(real_slot); + if( pr && pr->state!=STATE_EMPTY){ + + if(DMFCBase->IsPlayerDedicatedServer(pr)) + continue;//skip dedicated server + + //we have a valid play + ps = (tPlayerStat *)pr->user_info; + memset(buffer,' ',BUFSIZE); + + team = pr->team; + + sprintf(tempbuffer,"%d)",count); + memcpy(&buffer[0],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%.6s",DMFCBase->GetTeamString(team)); + memcpy(&buffer[5],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%s%s",(pr->state==STATE_INGAME)?"":"*",pr->callsign); + memcpy(&buffer[12],tempbuffer,strlen(tempbuffer)); + + if(ps){ + sprintf(tempbuffer,"%d[%d]",ps->Score[DSTAT_LEVEL],ps->Score[DSTAT_OVERALL]); + memcpy(&buffer[41],tempbuffer,strlen(tempbuffer)); + } + + sprintf(tempbuffer,"%d[%d]",pr->dstats.kills[DSTAT_LEVEL],pr->dstats.kills[DSTAT_OVERALL]); + memcpy(&buffer[53],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d[%d]",pr->dstats.deaths[DSTAT_LEVEL],pr->dstats.deaths[DSTAT_OVERALL]); + memcpy(&buffer[65],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d[%d]",pr->dstats.suicides[DSTAT_LEVEL],pr->dstats.suicides[DSTAT_OVERALL]); + memcpy(&buffer[76],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%s",DMFCBase->GetTimeString(DMFCBase->GetTimeInGame(real_slot))); + memcpy(&buffer[86],tempbuffer,strlen(tempbuffer)); + + int pos; + pos = 86 + strlen(tempbuffer) + 1; + if(posGetPlayerRecord(p); + if( pr && pr->state!=STATE_EMPTY) { + + if(DMFCBase->IsPlayerDedicatedServer(pr)) + continue;//skip dedicated server + + //Write out header + sprintf(buffer,"%d) %s%s",count,(pr->state==STATE_INGAME)?"":"*",pr->callsign); + DLLcf_WriteString(file,buffer); + length = strlen(buffer); + memset(buffer,'=',length); + buffer[length] = '\0'; + DLLcf_WriteString(file,buffer); + + //time in game + sprintf(buffer,TXT_STAT_TIG,DMFCBase->GetTimeString(DMFCBase->GetTimeInGame(p))); + DLLcf_WriteString(file,buffer); + + if(DMFCBase->FindPInfoStatFirst(p,&stat)){ + sprintf(buffer,TXT_STAT_HEADINGC); + DLLcf_WriteString(file,buffer); + + if(stat.slot!=p){ + memset(buffer,' ',BUFSIZE); + dpr = DMFCBase->GetPlayerRecord(stat.slot); + int pos; + + if(dpr) + { + sprintf(tempbuffer,"%s",dpr->callsign); + memcpy(buffer,tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d",stat.kills); + memcpy(&buffer[30],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d",stat.deaths); + memcpy(&buffer[40],tempbuffer,strlen(tempbuffer)); + + pos = 40 + strlen(tempbuffer) + 1; + if(posFindPInfoStatNext(&stat)){ + if(stat.slot!=p){ + int pos; + memset(buffer,' ',BUFSIZE); + dpr = DMFCBase->GetPlayerRecord(stat.slot); + if(dpr) + { + sprintf(tempbuffer,"%s",dpr->callsign); + memcpy(buffer,tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d",stat.kills); + memcpy(&buffer[30],tempbuffer,strlen(tempbuffer)); + + sprintf(tempbuffer,"%d",stat.deaths); + memcpy(&buffer[40],tempbuffer,strlen(tempbuffer)); + + pos = 40 + strlen(tempbuffer) + 1; + if(posFindPInfoStatClose(); + DLLcf_WriteString(file,""); //skip a line + count++; + } + } + + //done writing stats + DLLcfclose(file); + DLLAddHUDMessage(TXT_STAT_SAVED); +} + +#define ROOTFILENAME "CTF" +void OnSaveStatsToFile(void) +{ + char filename[256]; + DMFCBase->GenerateStatFilename(filename,ROOTFILENAME,false); + SaveStatsToFile(filename); +} + +void OnLevelEndSaveStatsToFile(void) +{ + char filename[256]; + DMFCBase->GenerateStatFilename(filename,ROOTFILENAME,true); + SaveStatsToFile(filename); +} + +void OnDisconnectSaveStatsToFile(void) +{ + char filename[256]; + DMFCBase->GenerateStatFilename(filename,ROOTFILENAME,false); + SaveStatsToFile(filename); +} + +void OnPrintScores(int level) +{ + char buffer[256]; + char name[70]; + int t,i; + int pos[6]; + int len[6]; + + + for(i=0;iGetTeamString(i),TeamScores[i]); + DPrintf(buffer); + } + + memset(buffer,' ',256); + pos[0] = 0; t = len[0] = 30; //give ample room for pilot name + pos[1] = pos[0] + t + 1; t = len[1] = strlen(TXT_POINTS); + pos[2] = pos[1] + t + 1; t = len[2] = strlen(TXT_KILLS_SHORT); + pos[3] = pos[2] + t + 1; t = len[3] = strlen(TXT_DEATHS_SHORT); + pos[4] = pos[3] + t + 1; t = len[4] = strlen(TXT_SUICIDES_SHORT); + pos[5] = pos[4] + t + 1; t = len[5] = strlen(TXT_PING); + + memcpy(&buffer[pos[0]],TXT_PILOT,strlen(TXT_PILOT)); + memcpy(&buffer[pos[1]],TXT_POINTS,len[1]); + memcpy(&buffer[pos[2]],TXT_KILLS_SHORT,len[2]); + memcpy(&buffer[pos[3]],TXT_DEATHS_SHORT,len[3]); + memcpy(&buffer[pos[4]],TXT_SUICIDES_SHORT,len[4]); + memcpy(&buffer[pos[5]],TXT_PING,len[5]); + buffer[pos[5]+len[5]+1] = '\n'; + buffer[pos[5]+len[5]+2] = '\0'; + DPrintf(buffer); + + int slot; + player_record *pr; + int pcount; + + if(level<0 || level>=MAX_PLAYER_RECORDS) + pcount = MAX_PLAYER_RECORDS; + else + pcount = level; + + int sortedplayers[MAX_PLAYER_RECORDS]; + DMFCBase->GetSortedPlayerSlots(sortedplayers,MAX_PLAYER_RECORDS); + + for(i=0;iGetPlayerRecord(slot); + if((pr)&&(pr->state!=STATE_EMPTY)){ + + if(DMFCBase->IsPlayerDedicatedServer(pr)) + continue; //skip dedicated server + + sprintf(name,"%s%s: %.8s",(pr->state==STATE_DISCONNECTED)?"*":"",pr->callsign,DMFCBase->GetTeamString(pr->team)); + name[29] = '\0'; + + tPlayerStat *stat; + stat = (tPlayerStat *)pr->user_info; + + memset(buffer,' ',256); + t = strlen(name); memcpy(&buffer[pos[0]],name,(tScore[DSTAT_LEVEL]:0); + t = strlen(name); memcpy(&buffer[pos[1]],name,(tdstats.kills[DSTAT_LEVEL]); + t = strlen(name); memcpy(&buffer[pos[2]],name,(tdstats.deaths[DSTAT_LEVEL]); + t = strlen(name); memcpy(&buffer[pos[3]],name,(tdstats.suicides[DSTAT_LEVEL]); + t = strlen(name); memcpy(&buffer[pos[4]],name,(tstate==STATE_INGAME) + sprintf(name,"%.0f",dNetPlayers[pr->pnum].ping_time*1000.0f); + else + strcpy(name,"---"); + t = strlen(name); memcpy(&buffer[pos[5]],name,(tGetLocalRole()==LR_SERVER){ + //if we are the server put the flag back in the center of the goal and tell all the players to do the same + DLLComputeRoomCenter(&fpos,&dRooms[GoalRooms[color]]); + int objnum = DLLObjCreate(OBJ_POWERUP,FlagIDs[color],GoalRooms[color],&fpos,NULL); + DLLMultiSendObject(&dObjects[objnum],1); + } + }else{ + //ok the flag is spewing out into the great beyond + //Start the timer! + Flag_timeout_timers[color] = DMFCBase->GetGametime() + FLAG_TIMEOUT_VALUE; + } + + //player has the flag + LoseFlagForPlayer(pnum,color,false); + } + //rotate flagmask so it is pointing at the next bit + flagmask = (flagmask>>1); + } + + // Reset colored balls + SetColoredBalls(pnum,true); + + + if(play_lose) + DoLoseFlag(DMFCBase->GetPlayerTeam(pnum)); +} + +///////////////////////////////////////////////////////////// +//CTF Functions +void DisplayHUDScores(struct tHUDItem *hitem) +{ + if(display_my_welcome) + { + //announce our arrival to ourselves (as server) + DisplayWelcomeMessage(DMFCBase->GetPlayerNum()); + display_my_welcome = false; + } + + if(!First_game_frame || DisplayScoreScreen) //interval hasn't been called yet or we are display the stats + return; + + ubyte alpha = DMFCBase->ConvertHUDAlpha((ubyte)((DisplayScoreScreen)?128:255)); + + int height = DLLgrfont_GetHeight((DMFCBase->GetGameFontTranslateArray())[HUD_FONT_INDEX]) + 3; + + int y = 170; + int x = 540; + int team = DMFCBase->GetPlayerTeam(DMFCBase->GetPlayerNum()); + int myteam = team; + int i; + + //Flag bitmaps + //if (HasFlag[team]!=-1) then draw a dimmed flag with the team flag of who has it on top + //if (HasFlag[team]==-1) && (FlagAtHome[team]==true) then draw normal flag + //if (HasFlag[team]==-1) && (FlagAtHome[team]==false) then draw dimmed flag + int cx,cy; + for(i=0;iGetPlayerTeam(HasFlag[i])],alpha); + } + else{ + if(FlagAtHome[i]){ + //draw normal flag + DLLRenderHUDQuad(cx,cy,DLLbm_w(FlagAHBmp[i],0),DLLbm_h(FlagAHBmp[i],0),0,0,1,1,FlagAHBmp[i],alpha); + } + else{ + //draw dimmed flag + int f_height = DLLbm_h(DimFlagAHBmp[i],0); + DLLRenderHUDQuad(cx,cy,DLLbm_w(DimFlagAHBmp[i],0),f_height,0,0,1,1,DimFlagAHBmp[i],alpha); + + //Draw timeout time + int time_left; + time_left = (int)( Flag_timeout_timers[i] - DMFCBase->GetGametime()); + if(time_left>0 && Flag_timeout_timers[i]!=0){ + int minutes; + minutes = time_left/60; + time_left = time_left%60; + DLLRenderHUDText(GR_GREEN,alpha,0,cx,cy+2+f_height,"%01d:%02d",minutes,time_left); + } + + } + } + } + } + + x = 520; + + if(Highlight_bmp<=BAD_BITMAP_HANDLE){ + //write the name of your team at the top of the screen since for some reason we don't a highlight bmp + DLLRenderHUDText(DMFCBase->GetTeamColor(team),alpha,0,x,y,TXT_TEAMFORM,DMFCBase->GetTeamString(team)); y+=height; + } + + //determine coordinates to use here + //we'll use a virtual width of 85 pixels on a 640x480 screen + //so first determine the new width + int name_width = 85.0f * DMFCBase->GetHudAspectX(); + int score_width = DLLgrtext_GetTextLineWidth("888"); + int name_x = DMFCBase->GetGameWindowW() - name_width - score_width - 10; + int score_x = DMFCBase->GetGameWindowW() - score_width - 5; + y = (DMFCBase->GetGameWindowH()/2) - ((height*DMFCBase->GetNumTeams())/2); + + //draw the team scores + for(team=0;team=CTFNumOfTeams) + continue; + + if((WhoJustScored!=i) || (DisplayScoreBlink) ){ + + //determine the number of players on the team + int num_players; + num_players = 0; + for(int w=0;wCheckPlayerNum(w) && dPlayers[w].team==i && !DMFCBase->IsPlayerDedicatedServer(w)) + num_players++; + } + + if(i==myteam && Highlight_bmp>BAD_BITMAP_HANDLE){ + //draw the highlite bar in the background + DLLrend_SetAlphaValue(alpha*0.50f); + DLLrend_SetZBufferState (0); + DLLrend_SetTextureType (TT_LINEAR); + DLLrend_SetLighting (LS_NONE); + DLLrend_SetAlphaType (AT_CONSTANT_TEXTURE); + + DLLrend_DrawScaledBitmap(name_x-2,y-2,score_x+score_width+2,y+height-1,Highlight_bmp,0,0,1,1,1.0); + DLLrend_SetZBufferState (1); + } + + char team_name[MAX_TEAMNAME_LEN+5]; + sprintf(team_name,"[%d]%s",num_players,DMFCBase->GetTeamString(i)); + //DMFCBase->ClipString(615 - x - 10,team_name,true); + //DLLRenderHUDText(DMFCBase->GetTeamColor(i),alpha,0,x,y,team_name); + //DLLRenderHUDText(DMFCBase->GetTeamColor(i),alpha,0,615,y,"%d",TeamScores[i]); + DMFCBase->ClipString(name_width,team_name,true); + + DLLgrtext_SetAlpha(alpha); + DLLgrtext_SetColor(DMFCBase->GetTeamColor(i)); + DLLgrtext_Printf(name_x,y,team_name); + DLLgrtext_Printf(score_x,y,"%d",TeamScores[i]); + + } + y+=height; + } + + //draw the bitmap for any flags you have currently + int flagcount; + int flagmask; + + flagcount = GetFlagCountForPlayer(DMFCBase->GetPlayerNum()); + flagmask = GetFlagMaskForPlayer(DMFCBase->GetPlayerNum()); + + if(flagcount==0) + return; + + y+=5; + + for(i=0;i>1; + } + +} + +#define compGT(a,b) (a < b) +void SortTeamScores(int *sortedindex,int *scores) +{ + int t; + int i, j; + + //copy scores into scoreinfo array + for(i=0;i=0 && compGT(scores[sortedindex[j]],scores[t]); j--){ + sortedindex[j+1] = sortedindex[j]; + } + // insert + sortedindex[j+1] = t; + } +} + +void DisplayWelcomeMessage(int player_num) +{ + char name_buffer[64]; + strcpy(name_buffer,(DMFCBase->GetPlayers())[player_num].callsign); + + if(player_num==DMFCBase->GetPlayerNum()) + { + DLLAddHUDMessage(TXT_WELCOME,name_buffer); + } + else + { + DLLAddHUDMessage(TXT_JOINED,name_buffer); + } +} + + +//adds a colored ball to a player (without removing what he has already) +void SetColoredBalls(int playernum,bool reset) +{ + float redb[4]; + float greenb[4]; + float blueb[4]; + + if(reset){ + DLLPlayerSetRotatingBall(playernum,0,0,NULL,NULL,NULL); + return; + } + + int flagcount; + int flagmask; + + bool red,blue,green,yellow; + red=blue=green=yellow = false; + + flagcount = GetFlagCountForPlayer(playernum); + flagmask = GetFlagMaskForPlayer(playernum); + + if(flagcount==0){ + DLLPlayerSetRotatingBall(playernum,0,0,NULL,NULL,NULL); + return; + } + + if(flagmask&FLAGMASK_REDTEAM) + red = true; + if(flagmask&FLAGMASK_BLUETEAM) + blue = true; + if(flagmask&FLAGMASK_GREENTEAM) + green = true; + if(flagmask&FLAGMASK_YELLOWTEAM) + yellow = true; + + for(int i=0;iSetNumberOfTeams(CTFNumOfTeams); +} + + +void DoFlagReturnedHome(int team) +{ + if(DMFCBase->GetPlayerTeam(DMFCBase->GetPlayerNum())==team){ + if(snd_return_ownteam!=-1) + DLLPlay2dSound(snd_return_ownteam); + }else{ + if(snd_return_otherteam!=-1) + DLLPlay2dSound(snd_return_otherteam); + } +} + +void DoLoseFlag(int team) +{ + if(DMFCBase->GetPlayerTeam(DMFCBase->GetPlayerNum())==team){ + if(snd_lose_ownteam!=-1) + DLLPlay2dSound(snd_lose_ownteam); + }else{ + if(snd_lose_otherteam!=-1) + DLLPlay2dSound(snd_lose_otherteam); + } + +} + +// VerifyFlagPosition +// Call this at certain intervals to verify a flags position. It will look at the +// flags room and makes sure that if it's in it's home room, the correct values +// are set, and vice versa. +void VerifyFlagPosition(void) +{ +} + +// AddFlagToPlayer +// gives a player a flag +bool AddFlagToPlayer(int pnum,int team,int flagobjnum) +{ + object *pobj = &dObjects[dPlayers[pnum].objnum]; + bool ret = true; + + if(DMFCBase->GetLocalRole()==LR_SERVER){ + //We're the server, so we need to create the flag and tell the clients, and then attach it + flagobjnum = DLLObjCreate(OBJ_POWERUP,AFlagIDs[team],pobj->roomnum,&pobj->pos,NULL); + + if(flagobjnum!=-1){ + //tell the clients that the flag has been created and they should attach it + TellClientsToAddorDelFlag(pnum,team,flagobjnum,true); + } + + // Attach the flag + + // 1st figure out how many flags the guy already has + // ------------------------------------------------- + int max_num_attach = 3; //based off chrishack for multiplayer + int num_attached = 0; + + if(!pobj->attach_children) + ret = false; + else + { + for(int ap=0;apattach_children[ap]!=OBJECT_HANDLE_NONE) + { + //attempt to make sure it's a valid object + object *tobj; + if(DLLObjGet(pobj->attach_children[ap],&tobj)) + { + num_attached++; + } + } + } + + // 2nd num_attached is the current number of flags this object has + // --------------------------------------------------------------- + switch(num_attached) + { + case 0: + { + //the easy case, nothing is attached, so just attach it to ap0 + ret = DLLAttachObject(pobj,0,&dObjects[flagobjnum],0,true); + }break; + + case 1: + { + bool retval; + object *tobj; + + //we should have a flag at ap0, move it to ap1 + ASSERT(pobj->attach_children[0]!=OBJECT_HANDLE_NONE); + int saved_ap0 = pobj->attach_children[0]; + retval = DLLUnattachChild(pobj,0); + ASSERT(retval); + + retval = DLLObjGet(saved_ap0,&tobj); + ASSERT(retval); + + //attach to ap1 + retval = DLLAttachObject(pobj,1,tobj,0,true); + ASSERT(retval); + + //attach new flag to ap2 + retval = DLLAttachObject(pobj,2,&dObjects[flagobjnum],0,true); + ASSERT(retval); + + ret = retval; + + }break; + + case 2: + { + //we should have a flag at ap1 and ap2 + //so just add this to ap3 + + //attach new flag to ap3 + ret = DLLAttachObject(pobj,0,&dObjects[flagobjnum],0,true); + + }break; + + case 3: + default: + { + Int3(); //Get Jeff + ret = false; + }break; + } + } + + if(!ret){ + //couldn't attach the flag + mprintf((0,"CTF: COULDN'T ATTACH FLAG TO PLAYER, DELETING\n")); + //tell the clients to remove this flag + DLLSetObjectDeadFlag(&dObjects[flagobjnum],true,false); + } + } + + if(flagobjnum==-1){ + //there was an error creating the flag...not good + mprintf((0,"CTF: Couldn't create/unhash flag for attachment\n")); + DMFCBase->DisconnectMe(); + return false; + } + + ChildFlags[team] = dObjects[flagobjnum].handle; + + return ret; +} + +// RemoveFlagFromPlayer +// removes a flag from a player +bool RemoveFlagFromPlayer(int pnum,int team) +{ + int flagobjnum = -1; + + if ( DMFCBase->GetLocalRole()==LR_SERVER) { + + if(ChildFlags[team]==OBJECT_HANDLE_NONE) + return false; + + object *fptr; + if(!DLLObjGet(ChildFlags[team],&fptr)){ + //the flag is already dead?!? + return false; + } + + DLLSetObjectDeadFlag(fptr,true,false); + + //tell the clients to remove the flag + TellClientsToAddorDelFlag(pnum,team,-1,false); + } + + ChildFlags[team] = OBJECT_HANDLE_NONE; + + return true; +} + +void TellClientsToAddorDelFlag(int pnum,int team,int objnum,bool add) +{ + if(add){ + //if we are adding a flag, than we need to send the object to them to make sure that + //they have it for when we go to process it + DLLMultiSendObject(&dObjects[objnum],false); + } + + ubyte data[MAX_GAME_DATA_SIZE]; + int size = 0; + DMFCBase->StartPacket(data,SPID_ADDDELFLAG,&size); + + MultiAddByte(pnum,data,&size); + MultiAddByte(team,data,&size); + MultiAddByte(add,data,&size); + + if(add){ + //add the objnum of the flag and pack it into the packet + MultiAddInt(objnum,data,&size); + } + + DMFCBase->SendPacket(data,size,SP_ALL); +} + +void ServerIsTellingMeToAddorDelAFlag(ubyte *data) +{ + int size = 0; + int pnum,team; + bool add; + + pnum = MultiGetByte(data,&size); + team = MultiGetByte(data,&size); + add = (MultiGetByte(data,&size))?true:false; + + //determine if we should add or delete a flag + if(add){ + int objnum; + objnum = MultiGetInt(data,&size); + objnum = DMFCBase->ConvertServerToLocalObjnum(objnum); + if(objnum==-1){ + //uh oh...corruption??? + FatalError("CTF: Server->Local Object Corruption\n"); + return; + } + AddFlagToPlayer(pnum,team,objnum); + }else{ + RemoveFlagFromPlayer(pnum,team); + } +} + + +///////////////////////////////// +//Timer event handlers +void OnTimer(void) +{ + DisplayFlagBlink = !DisplayFlagBlink; +} +void OnTimerKill(void) +{ + DisplayFlagBlink = true; + WhoJustFlagged = WhoJustFlaggedTimer = -1; +} + +void OnTimerScore(void) +{ + DisplayScoreBlink = !DisplayScoreBlink; +} +void OnTimerScoreKill(void) +{ + DisplayScoreBlink = true; + WhoJustScored = WhoJustScoredTimer = -1; +} + +/////////////////////////////////////////////////////////////////////////////////// +int PackByte(ubyte byte,ubyte *buffer,int pos) +{ + buffer[pos] = byte; + pos++; + return pos; +} + +int UnPackByte(ubyte *byte,ubyte *buffer,int pos) +{ + *byte = buffer[pos]; + pos++; + return pos; +} + +int PackBytes(ubyte *bytes,int count,ubyte *buffer,int pos) +{ + memcpy(&buffer[pos],bytes,count); + pos += count; + return pos; +} + +int UnPackBytes(ubyte *bytes,int count,ubyte *buffer,int pos) +{ + memcpy(bytes,&buffer[pos],count); + pos += count; + return pos; +} + +int PackWord(ushort word,ubyte *buffer,int pos) +{ + return PackBytes((ubyte *)&word,sizeof(ushort),buffer,pos); +} + +int UnPackWord(ushort *word,ubyte *buffer,int pos) +{ + return UnPackBytes((ubyte *)word,sizeof(ushort),buffer,pos); +} + +int PackInt(int data,ubyte *buffer,int pos) +{ + return PackBytes((ubyte *)&data,sizeof(int),buffer,pos); +} + +int UnPackInt(int *data,ubyte *buffer,int pos) +{ + return UnPackBytes((ubyte *)data,sizeof(int),buffer,pos); +} + +int PackArray(ubyte *data,int size,int count,ubyte *buffer,int pos) +{ + return PackBytes(data,size*count,buffer,pos); +} + +int UnPackArray(ubyte *data,int size,int count,ubyte *buffer,int pos) +{ + return UnPackBytes(data,size*count,buffer,pos); +} + +void SendGameState(int pnum) +{ + ubyte data[MAX_GAME_DATA_SIZE]; + int count = 0; + int i; + + DMFCBase->StartPacket(data,SPID_GAMESTATE,&count); + + //pack number of teams in this game + MultiAddInt(CTFNumOfTeams,data,&count); + + //pack flag whether someone has scored a hattrick + MultiAddByte(Someone_has_hattrick,data,&count); + + for(i=0;iSendPacket(data,count,pnum); +} + +void ReceiveGameState(ubyte *data) +{ + int count = 0; + int num_teams; + int i; + + for( i=0;iChildFlags and Attach the flags + for(i = 0; i ConvertServerToLocalObjnum(server_objnums[i]); + + if(our_objnum==-1){ + //fatal error + mprintf((0,"CTF: Local Objnums don't match server objnums\n")); + ChildFlags[i] = OBJECT_HANDLE_NONE; + DMFCBase->DisconnectMe(); + }else{ + //yeah! a valid objnum, attach it!!! + if(HasFlag[i]!=-1) + AddFlagToPlayer(HasFlag[i],i,our_objnum); + else{ + //hmm, HasFlag doesn't match ChildFlags + mprintf((0,"CTF: HasFlag doesn't match ChildFlags!!!!\n")); + ChildFlags[i] = OBJECT_HANDLE_NONE; + } + } + }else{ + //ok invalid... + ChildFlags[i] = OBJECT_HANDLE_NONE; + } + } +} + +/* +******************************************************************************************** +*/ + + +// returns the number of flags a player has, 0 if none, or an invalid pnum +int GetFlagCountForPlayer(int pnum) +{ + //1st check the pnum, make sure it is OK, is it isn't, return 0 + if(pnum<0 || pnum>=DLLMAX_PLAYERS){ + //invalid player number, return 0 flags + mprintf((0,"CTF: Invalid PNUM passed to GetFlagCountForPlayer()\n")); + return 0; + } + + int flag_count = 0; + //2nd, go through all the team flags, and check the player's inventory, see if they have the ID, + //if so, add it to their count + for(int i = 0; i < DLLMAX_TEAMS; i++){ + if(DLLInvCheckItem(pnum,OBJ_POWERUP,FlagIDs[i])){ + //they have this flag + flag_count++; + } + } + + return flag_count; +} + +// returns the mask of which flags this player currently has +ubyte GetFlagMaskForPlayer(int pnum) +{ + //1st check the pnum, make sure it is OK, if it isn't, return 0, meaning no flags + if(pnum<0 || pnum>=DLLMAX_PLAYERS){ + //invalid player number, return 0 flags + mprintf((0,"CTF: Invalid PNUM passed to GetFlagMaskForPlayer()\n")); + return 0; + } + + int flag_mask = 0; + ubyte mask = 0x01; + + //2nd go through all the teams flags, and check the player's inventory, see if they have the ID, + //if so, OR the current mask to the running flag_mask + for(int i = 0; i < DLLMAX_TEAMS; i++){ + if(DLLInvCheckItem(pnum,OBJ_POWERUP,FlagIDs[i])){ + //the have this flag + flag_mask |= mask; + } + //adjust the mask because we are moving to the next flag + mask = mask << 1; + } + + return flag_mask; +} + +// adds a flag to a player, as a precaution, it will go through all the players and makes sure that no one +// has the flag that is being added. If they are adding the flag, than remove that flag from whoever we thought had it +// it will return false if it had to remove a flag from a player +bool GivePlayerFlag(int pnum,ubyte team) +{ + //1st check the player num, make sure it is valid + if(!DMFCBase->CheckPlayerNum(pnum)){ + //not a valid player + mprintf((0,"CTF: Invalid pnum passed to GivePlayerFlag()\n")); + return false; + } + + //2nd check to make sure the team given is valid, and not our own team + if(team >= CTFNumOfTeams){ + //not a valid team + mprintf((0,"CTF: Invalid team passed to GivePlayerFlag() (team>=CTFNumOfTeams)\n")); + return false; + } + if(team == DMFCBase->GetPlayerTeam(pnum)){ + //we can't add a flag of the same team to a player + mprintf((0,"CTF: In GivePlayerFlag(), trying to add a player's home team flag\n")); + return false; + } + + //3rd, make sure no one else currently has this flag + //we'll check our HasFlags[] first + if(HasFlag[team]!=-1){ + //hmm, we have someone listed as already having this flag...odd + mprintf((0,"CTF: In GivePlayerFlag(), trying to add a flag, but we see someone else should already have it\n")); + int player = HasFlag[team]; + if(DMFCBase->CheckPlayerNum(player)){ + //this player is in the game... + //make sure this player doesn't have the flag in his inventory + while(DLLInvCheckItem(player,OBJ_POWERUP,FlagIDs[team])){ + //we have it listed that he does + mprintf((0,"CTF: In GivePlayerFlag(), we detected the flag in someone elses inventory\n")); + //remove all the flags that this player has of this team...very weird + DLLInvRemove(player,OBJ_POWERUP,FlagIDs[team]); + SetColoredBalls(player,false); + //check to see if the player had a flag attached to him + if(ChildFlags[team] != OBJECT_HANDLE_NONE && DMFCBase->GetLocalRole()==LR_SERVER){ + //he does have a flag attached to him...kill it + RemoveFlagFromPlayer(player,team); + } + } + } + //reset this value of the array + HasFlag[team] = -1; + if(DMFCBase->GetLocalRole()!=LR_SERVER){ + mprintf((0,"CTF: Game must be out of sync, requesting game state\n")); + DMFCBase->RequestGameState(); + } + } + + //loop through all the players and make sure they don't have this flag + for(int player = 0; player < DLLMAX_PLAYERS; player++ ){ + //check to see if it's an active player + if(!DMFCBase->CheckPlayerNum(player)) + continue; + + //remove all the flags the player has + while(DLLInvCheckItem(player,OBJ_POWERUP,FlagIDs[team])){ + mprintf((0,"CTF: In GivePlayerFlag(), detected a flag in a stranger's inventory\n")); + DLLInvRemove(player,OBJ_POWERUP,FlagIDs[team]); + SetColoredBalls(player,false); + //check to see if the player had a flag attached to him + if(ChildFlags[team]!=OBJECT_HANDLE_NONE && DMFCBase->GetLocalRole()==LR_SERVER){ + //he does have a flag attached to him...kill it + RemoveFlagFromPlayer(player,team); + } + } + } + + //ok, when we get here everything should be ducky, just add the flag and do the necessary things + DLLInvAddTypeID(pnum,OBJ_POWERUP,FlagIDs[team]); + HasFlag[team] = pnum; + SetColoredBalls(pnum); + + if(DMFCBase->GetLocalRole()==LR_SERVER){ + //so we got here and added a flag to the player, now we need to attach the flag to the player + if(!AddFlagToPlayer(pnum,team)){ + //there was an error adding the flag,,,,ack! + mprintf((0,"CTF: In GivePlayerFlag(), couldn't attach the flag to the player\n")); + } + } + + return true; +} + +//this function takes a flag away from the player, useful for when he scores, spews, disconnects, or observer modes +void LoseFlagForPlayer(int pnum,ubyte team,bool remove_from_inven) +{ + //1st check the player number + if(pnum<0 || pnum>=DLLMAX_PLAYERS){ + mprintf((0,"CTF:Invalid pnum passed to LoseFlagForPlayer()\n")); + return; + } + + //2nd check the team number + if(team>=CTFNumOfTeams){ + mprintf((0,"CTF:Invalid team passed to LoseFlagForPlayer()\n")); + return; + } + + if(team==DMFCBase->GetPlayerTeam(pnum)){ + mprintf((0,"CTF:Invalid team passed to LoseFlagForPlayer()...same team as player\n")); + return; + } + + //ok, we have it registered that the flag belongs to us + while(remove_from_inven && DLLInvCheckItem(pnum,OBJ_POWERUP,FlagIDs[team])){ + DLLInvRemove(pnum,OBJ_POWERUP,FlagIDs[team]); + } + + SetColoredBalls(pnum); + HasFlag[team] = -1; + + //check to see if the player had a flag attached to him + if(ChildFlags[team] != OBJECT_HANDLE_NONE){ + //he does have a flag attached to him...kill it + if(DMFCBase->GetLocalRole()==LR_SERVER){ + //remove this flag and tell the clients to do so, cause we're the server + RemoveFlagFromPlayer(pnum,team); + } + } +} + +void OnGetTokenString(char *src,char *dest,int dest_size) +{ + if(!stricmp(src,"flag")) + { + int mypnum = DMFCBase->GetPlayerNum(); + int flagcount = GetFlagCountForPlayer(mypnum); + int flagmask = GetFlagMaskForPlayer(mypnum); + int team; + bool hasflag[DLLMAX_TEAMS]; + + for(team=0;team>1; + } + for(;teamGetTeamString(team)); + break; + } + } + + strncpy(dest,t,dest_size-1); + dest[dest_size-1] = '\0'; + return; + }break; + case 2: + { + char t[2][64]; + int found = 0; + for(team=0;teamGetTeamString(team)); + found++; + if(found==flagcount) + break; + } + } + + char buffer[256]; + sprintf(buffer,"%s and %s",t[0],t[1]); + strncpy(dest,buffer,dest_size-1); + dest[dest_size-1] = '\0'; + return; + }break; + case 3: + { + char t[3][64]; + int found = 0; + for(team=0;teamGetTeamString(team)); + found++; + if(found==flagcount) + break; + } + } + + char buffer[256]; + sprintf(buffer,"%s, %s and %s",t[0],t[1],t[2]); + strncpy(dest,buffer,dest_size-1); + dest[dest_size-1] = '\0'; + return; + + }break; + default: + strncpy(dest,"No",dest_size-1); + dest[dest_size-1] = '\0'; + return; + break; + } + + } + + DMFCBase->OnGetTokenString(src,dest,dest_size); +} + +#ifdef MACINTOSH +#pragma export off +#endif \ No newline at end of file diff --git a/ctf/ctf.h b/ctf/ctf.h new file mode 100644 index 00000000..169d6a55 --- /dev/null +++ b/ctf/ctf.h @@ -0,0 +1,148 @@ +#ifndef __DMFC_APP_H_ +#define __DMFC_APP_H_ + +#include "osiris_share.h" +#include "d3events.h" + +// If a player dies, becomes an observer or disconnects, it's possible that they +// have a flag or more. This function will handle setting certain variables, timer +// and other various settings related to a flag spew +void HandlePlayerSpew(int pnum); +// AddFlagToPlayer +// gives a player a flag +bool AddFlagToPlayer(int pnum,int team,int flagobjnum = -1); +// RemoveFlagFromPlayer +// removes a flag from a player +bool RemoveFlagFromPlayer(int pnum,int team); + + +void OnInterval(void); +void OnHUDInterval(void); +void OnKeypress(int key); +void OnServerGameCreated(void); +void OnClientLevelStart(void); +void OnClientLevelEnd(void); +void OnGameStateRequest(int player_num); +void OnPlayerConnect(int player_num); +void OnClientPlayerKilled(object *killer_obj,int victim_pnum); +void OnServerCollide(object *me_obj,object *it_obj); +void OnClientCollide(ubyte *data); +void OnPLRInterval(void); +void OnPLRInit(void); +bool OnCanChangeTeam(int pnum,int newteam); +void OnSaveStatsToFile(void); +void OnLevelEndSaveStatsToFile(void); +void OnDisconnectSaveStatsToFile(void); +void OnPrintScores(int level); +void OnPlayerEntersObserver(int pnum,object *piggy); +void OnClientPlayerDisconnect(int player_num); +void OnPlayerChangeTeam(int player_num,int newteam,bool announce,bool spew_onrespawn); + +extern IDMFC *DMFCBase; + +// These next two function prototypes MUST appear in the extern "C" block if called +// from a CPP file. +#ifdef __cplusplus +extern "C" +{ +#endif + DLLEXPORT void DLLFUNCCALL DLLGameInit (int *api_func,ubyte *all_ok,int num_teams_to_use); + DLLEXPORT void DLLFUNCCALL DLLGameCall (int eventnum,dllinfo *data); + DLLEXPORT void DLLFUNCCALL DLLGameClose (); + DLLEXPORT void DLLFUNCCALL DLLGetGameInfo (tDLLOptions *options); + DLLEXPORT int DLLFUNCCALL GetGOScriptID(char *name,ubyte isdoor); + DLLEXPORT void DLLFUNCCALLPTR CreateInstance(int id); + DLLEXPORT void DLLFUNCCALL DestroyInstance(int id,void *ptr); + DLLEXPORT short DLLFUNCCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data); + DLLEXPORT int DLLFUNCCALL SaveRestoreState( void *file_ptr, ubyte saving_state ); +#ifdef __cplusplus +} +#endif + +#ifdef MACINTOSH +#pragma export on +#endif + +// The main entry point where the game calls the dll +void DLLFUNCCALL DLLGameCall (int eventnum,dllinfo *data) +{ + if((eventnumGetLocalRole()!=LR_SERVER)){ + return; + } + + DMFCBase->TranslateEvent(eventnum,data); +} + +// GetGOScriptID +// Purpose: +// Given the name of the object (from it's pagename), this function will search through it's +// list of General Object Scripts for a script with a matching name (to see if there is a script +// for that type/id of object within this DLL). If a matching scriptname is found, a UNIQUE ID +// is to be returned back to Descent 3. This ID will be used from here on out for all future +// interaction with the DLL. Since doors are not part of the generic object's, it's possible +// for a door to have the same name as a generic object (OBJ_POWERUP, OBJ_BUILDING, OBJ_CLUTTER +// or OBJ_ROBOT), therefore, a 1 is passed in for isdoor if the given object name refers to a +// door, else it is a 0. The return value is the unique identifier, else -1 if the script +// does not exist in the DLL. +int DLLFUNCCALL GetGOScriptID(char *name,ubyte isdoor) +{ + return -1; +} + +// CreateInstance +// Purpose: +// Given an ID from a call to GetGOScriptID(), this function will create a new instance for that +// particular script (by allocating and initializing memory, etc.). A pointer to this instance +// is to be returned back to Descent 3. This pointer will be passed around, along with the ID +// for CallInstanceEvent() and DestroyInstance(). Return NULL if there was an error. +void DLLFUNCCALLPTR CreateInstance(int id) +{ + return NULL; +} + +// DestroyInstance +// Purpose: +// Given an ID, and a pointer to a particular instance of a script, this function will delete and +// destruct all information associated with that script, so it will no longer exist. +void DLLFUNCCALL DestroyInstance(int id,void *ptr) +{ +} + +// CallInstanceEvent +// Purpose: +// Given an ID, a pointer to a script instance, an event and a pointer to the struct of +// information about the event, this function will translate who this event belongs to and +// passes the event to that instance of the script to be handled. Return a combination of +// CONTINUE_CHAIN and CONTINUE_DEFAULT, to give instructions on what to do based on the +// event. CONTINUE_CHAIN means to continue through the chain of scripts (custom script, level +// script, mission script, and finally default script). If CONTINUE_CHAIN is not specified, +// than the chain is broken and those scripts of lower priority will never get the event. Return +// CONTINUE_DEFAULT in order to tell D3 if you want process the normal action that is built into +// the game for that event. This only pertains to certain events. If the chain continues +// after this script, than the CONTINUE_DEFAULT setting will be overridden by lower priority +// scripts return value. +short DLLFUNCCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data) +{ + return CONTINUE_CHAIN|CONTINUE_DEFAULT; +} + +// SaveRestoreState +// Purpose: +// This function is called when Descent 3 is saving or restoring the game state. In this function +// you should save/restore any global data that you want preserved through load/save (which includes +// demos). You must be very careful with this function, corrupting the file (reading or writing too +// much or too little) may be hazardous to the game (possibly making it impossible to restore the +// state). It would be best to use version information to keep older versions of saved states still +// able to be used. IT IS VERY IMPORTANT WHEN SAVING THE STATE TO RETURN THE NUMBER OF _BYTES_ WROTE +// TO THE FILE. When restoring the data, the return value is ignored. saving_state is 1 when you should +// write data to the file_ptr, 0 when you should read in the data. +int DLLFUNCCALL SaveRestoreState( void *file_ptr, ubyte saving_state ) +{ + return 0; +} + +#ifdef MACINTOSH +#pragma export off +#endif + +#endif diff --git a/editor/AISettingsDlg.cpp b/editor/AISettingsDlg.cpp new file mode 100644 index 00000000..db03a8aa --- /dev/null +++ b/editor/AISettingsDlg.cpp @@ -0,0 +1,729 @@ +// AISettingsDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "AISettingsDlg.h" +#include "mono.h" +#include "soundload.h" +#include "pserror.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define MAX_SLIDER_RANGE 100 + +///////////////////////////////////////////////////////////////////////////// +// CAISettingsDlg dialog + + +CAISettingsDlg::CAISettingsDlg(t_ai_info *ai_info,CWnd* pParent /*=NULL*/) + : CDialog(CAISettingsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CAISettingsDlg) + m_ai_class = _T(""); + m_ai_flock_alignment = 0.0f; + m_ai_flock_cohesion = 0.0f; + m_ai_flock_member_check = FALSE; + m_ai_flock_seperation = 0.0f; + m_initial_action = _T(""); + m_ai_uses_thrust_check = FALSE; + m_ai_type = _T(""); + m_ai_movement_type = _T(""); + m_ai_movement_subtype = _T(""); + m_fluctuate_speed_properties_check = FALSE; + m_ai_max_turn_rate_time = 0.0f; + m_angry_sound_combo = _T(""); + m_attack_sound_combo = _T(""); + m_circle_distance = 0.0f; + m_attack_vel_percent = 0.0f; + m_dogde_percent = 0.0f; + m_dodge_vel_percent = 0.0f; + m_flee_sound_combo = _T(""); + m_flee_vel_percent = 0.0f; + m_melee1_latency = 0.0f; + m_melee1_distance = 0.0f; + m_melee2_distance = 0.0f; + m_melee2_latency = 0.0f; + m_see_sound_combo = _T(""); + m_ordered_wb_firing_check = FALSE; + m_orient_to_vel = FALSE; + m_xz_dist = FALSE; + m_target_by_dist_check = FALSE; + m_turret_sound_combo = _T(""); + m_avoid_friends_check = FALSE; + m_avoid_friends_dist = 0.0f; + m_bfhmax = 0.0f; + m_bfhmin = 0.0f; + m_bfh_check = FALSE; + m_fov_uvec = FALSE; + m_fov_aim = FALSE; + //}}AFX_DATA_INIT + + //Store the pointer to the stucture we're editing + m_ai_info = ai_info; + + //Copy out the data + m_ai_class = Ai_class_strings[ai_info->ai_class]; + m_ai_type = Ai_type_strings[ai_info->ai_type]; + + m_ai_movement_type = Ai_movement_type_strings[ai_info->movement_type]; + if(!stricmp(m_ai_movement_type,"Walking")) + { + m_ai_movement_subtype = Ai_movement_subtype_walking_strings[ai_info->movement_subtype]; + } + else if (!stricmp(m_ai_movement_type,"Flying")) + { + m_ai_movement_subtype = Ai_movement_subtype_flying_strings[ai_info->movement_subtype]; + } + else + { + m_ai_movement_subtype = ""; + } + + m_ai_max_velocity = ai_info->max_velocity; + + if(ai_info->max_delta_velocity > 0.0) + { + m_ai_max_vel_time = ai_info->max_velocity / ai_info->max_delta_velocity; + } + else + { + m_ai_max_vel_time = 1.0f; + m_ai_max_velocity = 0.0f; + } + + m_ai_max_turn_rate = ai_info->max_turn_rate; + + m_ai_fov = acos(ai_info->fov)*(360.0/PI); +// mprintf((0, "FOV = %f\n.", ai_info->fov)); + + m_orient_to_vel = (ai_info->flags & AIF_ORIENT_TO_VEL) != 0; + m_xz_dist = (ai_info->flags & AIF_XZ_DIST) != 0; + + m_avoid_friends_check = (ai_info->flags & AIF_AUTO_AVOID_FRIENDS) != 0; + m_avoid_friends_dist = ai_info->avoid_friends_distance; + + m_fire_weapon1 = (ai_info->flags & AIF_WEAPON1) != 0; + m_fire_weapon2 = (ai_info->flags & AIF_WEAPON2) != 0; + m_melee1 = (ai_info->flags & AIF_MELEE1) != 0; + m_melee2 = (ai_info->flags & AIF_MELEE2) != 0; + + m_stay_inout = (ai_info->flags & AIF_STAYS_INOUT) != 0; + + m_persistant_check = (ai_info->flags & AIF_PERSISTANT) != 0; + m_dodge_check = (ai_info->flags & AIF_DODGE) != 0; + m_fireattarget_check = (ai_info->flags & AIF_FIRE) != 0; + m_flinch_check = (ai_info->flags & AIF_FLINCH) != 0; + m_retarget_check = (ai_info->flags & AIF_DETERMINE_TARGET) != 0; + m_turretcontrol_check = (ai_info->flags & AIF_AIM) != 0; + m_tauntatdeath_check = (ai_info->flags & AIF_ONLY_TAUNT_AT_DEATH) != 0; + m_avoidwalls_check = (ai_info->flags & AIF_AVOID_WALLS) != 0; + m_ordered_wb_firing_check = (ai_info->flags & AIF_ORDERED_WB_FIRING) != 0; + m_target_by_dist_check = (ai_info->flags & AIF_TARGET_BY_DIST) != 0; + m_bfh_check = (ai_info->flags & AIF_BIASED_FLIGHT_HEIGHT) != 0; + m_fov_uvec = (ai_info->flags & AIF_UVEC_FOV) != 0; + m_fov_aim = (ai_info->flags & AIF_AIM_PNT_FOV) != 0; + + m_fluctuate_speed_properties_check = (ai_info->flags & AIF_FLUCTUATE_SPEED_PROPERTIES) != 0; + + m_notify_hears_noise = (ai_info->notify_flags & (0x00000001 << AIN_HEAR_NOISE)) != 0; + m_notify_hitbyweapon_check = (ai_info->notify_flags & (0x00000001 << AIN_HIT_BY_WEAPON)) != 0; + m_notify_nearwall_check = (ai_info->notify_flags & (0x00000001 << AIN_NEAR_WALL)) != 0; + m_notify_objectfired_check = (ai_info->notify_flags & (0x00000001 << AIN_OBJ_FIRED)) != 0; + m_notify_seeplayer_check = (ai_info->notify_flags & (0x00000001 << AIN_SEE_TARGET)) != 0; + m_notify_weaponhittarget_check = (ai_info->notify_flags & (0x00000001 << AIN_WHIT_OBJECT)) != 0; + + if(ai_info->max_delta_turn_rate > 0.0) + { + m_ai_max_turn_rate_time = ai_info->max_turn_rate / ai_info->max_delta_turn_rate; + } + else + { + m_ai_max_turn_rate_time = 1.0f; + m_ai_max_turn_rate = 0.0f; + } + + m_circle_distance = ai_info->circle_distance; + m_attack_vel_percent = ai_info->attack_vel_percent * 100.0f; + m_dogde_percent = ai_info->dodge_percent * 100.0f; + m_dodge_vel_percent = ai_info->dodge_vel_percent * 100.0f; + m_flee_vel_percent = ai_info->flee_vel_percent * 100.0f; + m_melee1_distance = ai_info->melee_damage[0]; + m_melee2_distance = ai_info->melee_damage[1]; + m_melee1_latency = ai_info->melee_latency[0]; + m_melee2_latency = ai_info->melee_latency[1]; + + m_bfhmin = ai_info->biased_flight_min; + m_bfhmax = ai_info->biased_flight_max; + + m_angry_sound_combo = Sounds[ai_info->sound[AI_ANGRY_SOUND]].name; + m_attack_sound_combo = Sounds[ai_info->sound[AI_ATTACK_SOUND]].name; + m_flee_sound_combo = Sounds[ai_info->sound[AI_FLEE_SOUND]].name; + m_see_sound_combo = Sounds[ai_info->sound[AI_SEE_SOUND]].name; + m_turret_sound_combo = Sounds[ai_info->sound[AI_TURRET_SOUND]].name; +} + + +void CAISettingsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAISettingsDlg) + DDX_Control(pDX, IDC_BFHI_SLIDER, m_bfhi_slider); + DDX_Control(pDX, IDC_AI_TLV_SLIDER, m_tlv_slider); + DDX_Control(pDX, IDC_AI_TLA_SLIDER, m_tla_slider); + DDX_Control(pDX, IDC_AI_ROAMING_SLIDER, m_roaming_slider); + DDX_Control(pDX, IDC_AI_NV_SLIDER, m_nv_slider); + DDX_Control(pDX, IDC_AI_LIFE_PRESERVATION_SLIDER, m_lp_slider); + DDX_Control(pDX, IDC_AI_HEARING_SLIDER, m_hearing_slider); + DDX_Control(pDX, IDC_AI_FV_SLIDER, m_fv_slider); + DDX_Control(pDX, IDC_AI_FRUSTRATION_SLIDER, m_frustration_slider); + DDX_Control(pDX, IDC_AI_FIGHT_TEAM_SLIDER, m_fight_team_slider); + DDX_Control(pDX, IDC_AI_FIGHT_SAME_SLIDER, m_fight_same_slider); + DDX_Control(pDX, IDC_AI_CURIOUSITY_SLIDER, m_curiousity_slider); + DDX_Control(pDX, IDC_AI_AGRESSION_SLIDER, m_agression_slider); + DDX_Control(pDX, IDC_AI_FIRE_SPREAD_SLIDER, m_fire_spread_slider); + DDX_Check(pDX, IDC_AI_FIRE_WEAPON_1_CHECK, m_fire_weapon1); + DDX_Check(pDX, IDC_AI_FIRE_WEAPON_2_CHECK, m_fire_weapon2); + DDX_Check(pDX, IDC_AI_MELEE_1_CHECK, m_melee1); + DDX_Check(pDX, IDC_AI_MELEE_2_CHECK, m_melee2); + DDX_Check(pDX, IDC_AI_STAY_IN_OUT_CHECK, m_stay_inout); + DDX_CBString(pDX, IDC_AI_CLASS_COMBO, m_ai_class); + DDX_Text(pDX, IDC_AI_FOV_EDIT, m_ai_fov); + DDV_MinMaxFloat(pDX, m_ai_fov, 0.0f, 360.0f); + DDX_CBString(pDX, IDC_AI_INITIAL_ACTION_COMBO, m_initial_action); + DDX_Check(pDX, IDC_AI_USES_THRUST_CHECK, m_ai_uses_thrust_check); + DDX_CBString(pDX, IDC_AI_TYPE_COMBO, m_ai_type); + DDX_CBString(pDX, IDC_AI_MOVEMENT_TYPE_COMBO, m_ai_movement_type); + DDX_CBString(pDX, IDC_AI_MOVEMENT_SUBTYPE_COMBO, m_ai_movement_subtype); + DDX_Text(pDX, IDC_AI_MAX_VELOCITY_EDIT, m_ai_max_velocity); + DDX_Text(pDX, IDC_AI_MAX_VEL_TIME_EDIT, m_ai_max_vel_time); + DDX_Text(pDX, IDC_AI_MAX_TURN_RATE_EDIT, m_ai_max_turn_rate); + DDX_Check(pDX, IDC_AI_DODGE_CHECK, m_dodge_check); + DDX_Check(pDX, IDC_AI_FIREATTARGET_CHECK, m_fireattarget_check); + DDX_Check(pDX, IDC_AI_FLINCH_CHECK, m_flinch_check); + DDX_Check(pDX, IDC_AI_NOTIFY_HITBYWEAPON_CHECK, m_notify_hitbyweapon_check); + DDX_Check(pDX, IDC_AI_NOTIFY_NEARWALL_CHECK, m_notify_nearwall_check); + DDX_Check(pDX, IDC_AI_NOTIFY_OBJFIRED_CHECK, m_notify_objectfired_check); + DDX_Check(pDX, IDC_AI_NOTIFY_SEEPLAYER_CHECK, m_notify_seeplayer_check); + DDX_Check(pDX, IDC_AI_NOTIFY_WEAPONHITPLAYER_CHECK, m_notify_weaponhittarget_check); + DDX_Check(pDX, IDC_AI_RETARGET_CHECK, m_retarget_check); + DDX_Check(pDX, IDC_AUTO_TURRETCONTROL_CHECK, m_turretcontrol_check); + DDX_Check(pDX, IDC_TAUNTATDEATH_CHECK, m_tauntatdeath_check); + DDX_Check(pDX, IDC_AI_AVOIDWALLS_CHECK, m_avoidwalls_check); + DDX_Check(pDX, IDC_HEARS_NOISE_CHECK, m_notify_hears_noise); + DDX_Check(pDX, IDC_PERSISTANT_CHECK, m_persistant_check); + DDX_Check(pDX, IDC_AI_FLUCTUATE_PROPERTIES, m_fluctuate_speed_properties_check); + DDX_Text(pDX, IDC_AI_MAX_TURN_RATE_TIME_EDIT, m_ai_max_turn_rate_time); + DDV_MinMaxFloat(pDX, m_ai_max_turn_rate_time, 0.0f, 1.e+007f); + DDX_CBString(pDX, IDC_AI_ANGRY_SOUND_COMBO, m_angry_sound_combo); + DDX_CBString(pDX, IDC_AI_ATTACK_SOUND_COMBO, m_attack_sound_combo); + DDX_Text(pDX, IDC_AI_CIRCLE_DISTANCE_EDIT, m_circle_distance); + DDV_MinMaxFloat(pDX, m_circle_distance, 0.0f, 10000.0f); + DDX_Text(pDX, IDC_AI_ATTACK_VEL_PER_EDIT, m_attack_vel_percent); + DDV_MinMaxFloat(pDX, m_attack_vel_percent, 0.0f, 10000.0f); + DDX_Text(pDX, IDC_AI_DODGE_PER_EDIT, m_dogde_percent); + DDV_MinMaxFloat(pDX, m_dogde_percent, 0.0f, 100.0f); + DDX_Text(pDX, IDC_AI_DODGE_VEL_PER_EDIT, m_dodge_vel_percent); + DDV_MinMaxFloat(pDX, m_dodge_vel_percent, 0.f, 10000.f); + DDX_CBString(pDX, IDC_AI_FLEE_SOUND_COMBO, m_flee_sound_combo); + DDX_Text(pDX, IDC_AI_FLEE_VEL_PER_EDIT, m_flee_vel_percent); + DDV_MinMaxFloat(pDX, m_flee_vel_percent, 0.0f, 10000.0f); + DDX_Text(pDX, IDC_AI_MELEE1_LATENCY_EDIT, m_melee1_latency); + DDX_Text(pDX, IDC_AI_MELEE1_DIST_EDIT, m_melee1_distance); + DDV_MinMaxFloat(pDX, m_melee1_distance, 0.0f, 10000.0f); + DDX_Text(pDX, IDC_AI_MELEE2_DIST_EDIT, m_melee2_distance); + DDV_MinMaxFloat(pDX, m_melee2_distance, 0.0f, 10000.0f); + DDX_Text(pDX, IDC_AI_MELEE2_LATENCY_EDIT, m_melee2_latency); + DDV_MinMaxFloat(pDX, m_melee2_latency, 0.0f, 10000.0f); + DDX_CBString(pDX, IDC_AI_SEE_SOUND_COMBO, m_see_sound_combo); + DDX_Check(pDX, IDC_AI_ORDERED_WB_FIRING_CHECK, m_ordered_wb_firing_check); + DDX_Check(pDX, IDC_AI_ORIENT_VEL_CHECK, m_orient_to_vel); + DDX_Check(pDX, IDC_AI_XZ_TARGET_DIST, m_xz_dist); + DDX_Check(pDX, IDC_AI_TARGET_BY_DIST_CHECK, m_target_by_dist_check); + DDX_CBString(pDX, IDC_AI_TURRET_SOUND_COMBO, m_turret_sound_combo); + DDX_Check(pDX, IDC_AI_AVOID_FRIENDS_CHECK, m_avoid_friends_check); + DDX_Text(pDX, IDC_AVOID_FRIENDS_DIST_EDIT, m_avoid_friends_dist); + DDV_MinMaxFloat(pDX, m_avoid_friends_dist, 0.f, 300.f); + DDX_Text(pDX, IDC_BFHMAX_EDIT, m_bfhmax); + DDX_Text(pDX, IDC_BFHMIN_EDIT, m_bfhmin); + DDX_Check(pDX, IDC_BFH_CHECK, m_bfh_check); + DDX_Check(pDX, IDC_AI_AIM_WITH_UVEC, m_fov_uvec); + DDX_Check(pDX, IDC_AIM_FOV_CHECK, m_fov_aim); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CAISettingsDlg, CDialog) + //{{AFX_MSG_MAP(CAISettingsDlg) + ON_CBN_SELCHANGE(IDC_AI_MOVEMENT_TYPE_COMBO, OnSelchangeAiMovementTypeCombo) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CAISettingsDlg message handlers + +BOOL CAISettingsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + int i; + CButton *bbox; + + switch(m_ai_info->flags & AIF_TEAM_MASK) + { + case AIF_TEAM_PTMC: + bbox = (CButton *)GetDlgItem(IDC_AI_PTMC_RADIO); + break; + case AIF_TEAM_REBEL: + bbox = (CButton *)GetDlgItem(IDC_AI_REBEL_RADIO); + break; + case AIF_TEAM_NEUTRAL: + bbox = (CButton *)GetDlgItem(IDC_AI_NEUTRAL_RADIO); + break; + case AIF_TEAM_HOSTILE: + bbox = (CButton *)GetDlgItem(IDC_AI_HOSTILE_RADIO); + break; + } + + bbox->SetCheck(true); + + SendDlgItemMessage( IDC_AI_ANGRY_SOUND_COMBO, CB_RESETCONTENT,0,0); + for (i=0;ifire_spread * MAX_SLIDER_RANGE)); + + m_bfhi_slider.SetRange(0, MAX_SLIDER_RANGE); + m_bfhi_slider.SetPos((int)(m_ai_info->biased_flight_importance * MAX_SLIDER_RANGE)); + + m_nv_slider.SetRange(0, MAX_SLIDER_RANGE); + m_nv_slider.SetPos((int)(m_ai_info->night_vision * MAX_SLIDER_RANGE)); + + m_fv_slider.SetRange(0, MAX_SLIDER_RANGE); + m_fv_slider.SetPos((int)(m_ai_info->fog_vision * MAX_SLIDER_RANGE)); + + m_curiousity_slider.SetRange(0, MAX_SLIDER_RANGE); + m_curiousity_slider.SetPos((int)(m_ai_info->curiousity * MAX_SLIDER_RANGE)); + + m_tla_slider.SetRange(0, MAX_SLIDER_RANGE); + m_tla_slider.SetPos((int)(m_ai_info->lead_accuracy * MAX_SLIDER_RANGE)); + + m_tlv_slider.SetRange(0, MAX_SLIDER_RANGE); + m_tlv_slider.SetPos((int)(m_ai_info->lead_varience * MAX_SLIDER_RANGE)); + + m_fight_team_slider.SetRange(0, MAX_SLIDER_RANGE); + m_fight_team_slider.SetPos((int)(m_ai_info->fight_team * MAX_SLIDER_RANGE)); + + m_fight_same_slider.SetRange(0, MAX_SLIDER_RANGE); + m_fight_same_slider.SetPos((int)(m_ai_info->fight_same * MAX_SLIDER_RANGE)); + + m_agression_slider.SetRange(0, MAX_SLIDER_RANGE); + m_agression_slider.SetPos((int)(m_ai_info->agression * MAX_SLIDER_RANGE)); + + m_hearing_slider.SetRange(0, MAX_SLIDER_RANGE); + m_hearing_slider.SetPos((int)(m_ai_info->hearing * MAX_SLIDER_RANGE)); + + m_frustration_slider.SetRange(0, MAX_SLIDER_RANGE); + m_frustration_slider.SetPos((int)(m_ai_info->frustration * MAX_SLIDER_RANGE)); + + m_roaming_slider.SetRange(0, MAX_SLIDER_RANGE); + m_roaming_slider.SetPos((int)(m_ai_info->roaming * MAX_SLIDER_RANGE)); + + m_lp_slider.SetRange(0, MAX_SLIDER_RANGE); + m_lp_slider.SetPos((int)(m_ai_info->life_preservation * MAX_SLIDER_RANGE)); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CAISettingsDlg::OnSelchangeAiMovementTypeCombo() +{ + int i; + + int cur; + char name[200]; + + if(!UpdateData(true)) return; + + cur=SendDlgItemMessage( IDC_AI_MOVEMENT_TYPE_COMBO, CB_GETCURSEL,0,0); + SendDlgItemMessage( IDC_AI_MOVEMENT_TYPE_COMBO, CB_GETLBTEXT,cur,(LPARAM) (LPCTSTR)name); + + m_ai_movement_type = name; + + UpdateData(false); + + SendDlgItemMessage( IDC_AI_MOVEMENT_SUBTYPE_COMBO, CB_RESETCONTENT,0,0); + if(!stricmp(m_ai_movement_type, "FLYING")) + { + for (i=0;iflags &= ~AIF_TEAM_MASK; + + if(((CButton *)GetDlgItem(IDC_AI_PTMC_RADIO))->GetCheck()) + m_ai_info->flags |= AIF_TEAM_PTMC; + else if(((CButton *)GetDlgItem(IDC_AI_REBEL_RADIO))->GetCheck()) + m_ai_info->flags |= AIF_TEAM_REBEL; + else if(((CButton *)GetDlgItem(IDC_AI_NEUTRAL_RADIO))->GetCheck()) + m_ai_info->flags |= AIF_TEAM_NEUTRAL; + else if(((CButton *)GetDlgItem(IDC_AI_HOSTILE_RADIO))->GetCheck()) + m_ai_info->flags |= AIF_TEAM_HOSTILE; + else + { + mprintf((0, "ERROR: No team\n")); + Int3(); + } + + if (m_fire_weapon1) + m_ai_info->flags |= AIF_WEAPON1; + else + m_ai_info->flags &= ~AIF_WEAPON1; + + if (m_fire_weapon2) + m_ai_info->flags |= AIF_WEAPON2; + else + m_ai_info->flags &= ~AIF_WEAPON2; + + if (m_melee1) + m_ai_info->flags |= AIF_MELEE1; + else + m_ai_info->flags &= ~AIF_MELEE1; + + if(m_orient_to_vel) + m_ai_info->flags |= AIF_ORIENT_TO_VEL; + else + m_ai_info->flags &= ~AIF_ORIENT_TO_VEL; + + if(m_xz_dist) + m_ai_info->flags |= AIF_XZ_DIST; + else + m_ai_info->flags &= ~AIF_XZ_DIST; + + if(m_avoid_friends_check) + m_ai_info->flags |= AIF_AUTO_AVOID_FRIENDS; + else + m_ai_info->flags &= ~AIF_AUTO_AVOID_FRIENDS; + + if (m_melee2) + m_ai_info->flags |= AIF_MELEE2; + else + m_ai_info->flags &= ~AIF_MELEE2; + + if (m_stay_inout) + m_ai_info->flags |= AIF_STAYS_INOUT; + else + m_ai_info->flags &= ~AIF_STAYS_INOUT; + + for(i = 0; i < MAX_AI_INIT_CLASSES; i++) + { + if(!stricmp(m_ai_class, Ai_class_strings[i])) + { + m_ai_info->ai_class = i; + break; + } + } + ASSERT(i < MAX_AI_INIT_CLASSES); + + for(i = 0; i < MAX_AI_INIT_TYPES; i++) + { + if(!stricmp(m_ai_type, Ai_type_strings[i])) + { + m_ai_info->ai_type = i; + break; + } + } + ASSERT(i < MAX_AI_INIT_TYPES); + + for(i = 0; i < MAX_AI_INIT_MOVEMENT_TYPES; i++) + { + if(!stricmp(m_ai_movement_type, Ai_movement_type_strings[i])) + { + m_ai_info->movement_type = i; + break; + } + } + ASSERT(i < MAX_AI_INIT_MOVEMENT_TYPES); + + if(!stricmp(m_ai_movement_type,"WALKING")) + { + for(i = 0; i < MAX_AI_INIT_MOVEMENT_SUBTYPES; i++) + { + if(!stricmp(m_ai_movement_subtype, Ai_movement_subtype_walking_strings[i])) + { + m_ai_info->movement_subtype = i; + break; + } + } + ASSERT(i < MAX_AI_INIT_MOVEMENT_SUBTYPES); + } + else if (!stricmp(m_ai_movement_type,"FLYING")) + { + for(i = 0; i < MAX_AI_INIT_MOVEMENT_SUBTYPES; i++) + { + if(!stricmp(m_ai_movement_subtype, Ai_movement_subtype_flying_strings[i])) + { + m_ai_info->movement_subtype = i; + break; + } + } + ASSERT(i < MAX_AI_INIT_MOVEMENT_SUBTYPES); + } + else + { + m_ai_info->movement_subtype = 0; + } + + m_ai_info->max_velocity = m_ai_max_velocity; + if(m_ai_max_vel_time > 0.0f) + m_ai_info->max_delta_velocity = m_ai_max_velocity / m_ai_max_vel_time; + else + m_ai_info->max_delta_velocity = 0.0f; + m_ai_info->max_turn_rate = m_ai_max_turn_rate; + + if(m_persistant_check) + m_ai_info->flags |= AIF_PERSISTANT; + else + m_ai_info->flags &= ~AIF_PERSISTANT; + + if(m_dodge_check) + m_ai_info->flags |= AIF_DODGE; + else + m_ai_info->flags &= ~AIF_DODGE; + if(m_fireattarget_check) + m_ai_info->flags |= AIF_FIRE; + else + m_ai_info->flags &= ~AIF_FIRE; + if(m_flinch_check) + m_ai_info->flags |= AIF_FLINCH; + else + m_ai_info->flags &= ~AIF_FLINCH; + if(m_retarget_check) + m_ai_info->flags |= AIF_DETERMINE_TARGET; + else + m_ai_info->flags &= ~AIF_DETERMINE_TARGET; + if(m_turretcontrol_check) + m_ai_info->flags |= AIF_AIM; + else + m_ai_info->flags &= ~AIF_AIM; + if(m_tauntatdeath_check) + m_ai_info->flags |= AIF_ONLY_TAUNT_AT_DEATH; + else + m_ai_info->flags &= ~AIF_ONLY_TAUNT_AT_DEATH; + if(m_avoidwalls_check) + m_ai_info->flags |= AIF_AVOID_WALLS; + else + m_ai_info->flags &= ~AIF_AVOID_WALLS; + if(m_fluctuate_speed_properties_check) + m_ai_info->flags |= AIF_FLUCTUATE_SPEED_PROPERTIES; + else + m_ai_info->flags &= ~AIF_FLUCTUATE_SPEED_PROPERTIES; + if(m_ordered_wb_firing_check) + m_ai_info->flags |= AIF_ORDERED_WB_FIRING; + else + m_ai_info->flags &= ~AIF_ORDERED_WB_FIRING; + if(m_target_by_dist_check) + m_ai_info->flags |= AIF_TARGET_BY_DIST; + else + m_ai_info->flags &= ~AIF_TARGET_BY_DIST; + + if(m_bfh_check) + m_ai_info->flags |= AIF_BIASED_FLIGHT_HEIGHT; + else + m_ai_info->flags &= ~AIF_BIASED_FLIGHT_HEIGHT; + + if(m_fov_uvec) + m_ai_info->flags |= AIF_UVEC_FOV; + else + m_ai_info->flags &= ~AIF_UVEC_FOV; + + if(m_fov_aim) + m_ai_info->flags |= AIF_AIM_PNT_FOV; + else + m_ai_info->flags &= ~AIF_AIM_PNT_FOV; + + if(m_notify_hears_noise) + m_ai_info->notify_flags |= (0x00000001 << AIN_HEAR_NOISE); + else + m_ai_info->notify_flags &= ~(0x00000001 << AIN_HEAR_NOISE); + + if(m_notify_hitbyweapon_check) + m_ai_info->notify_flags |= (0x00000001 << AIN_HIT_BY_WEAPON); + else + m_ai_info->notify_flags &= ~(0x00000001 << AIN_HIT_BY_WEAPON); + + if(m_notify_nearwall_check) + m_ai_info->notify_flags |= (0x00000001 << AIN_NEAR_WALL); + else + m_ai_info->notify_flags &= ~(0x00000001 << AIN_NEAR_WALL); + + if(m_notify_objectfired_check) + m_ai_info->notify_flags |= (0x00000001 << AIN_OBJ_FIRED); + else + m_ai_info->notify_flags &= ~(0x00000001 << AIN_OBJ_FIRED); + + if(m_notify_seeplayer_check) + m_ai_info->notify_flags |= (0x00000001 << AIN_SEE_TARGET); + else + m_ai_info->notify_flags &= ~(0x00000001 << AIN_SEE_TARGET); + + if(m_notify_weaponhittarget_check) + m_ai_info->notify_flags |= (0x00000001 << AIN_WHIT_OBJECT); + else + m_ai_info->notify_flags &= ~(0x00000001 << AIN_WHIT_OBJECT); + + m_ai_info->fov = cos(m_ai_fov*PI/(360.0)); + + if(m_ai_max_turn_rate_time > 0.0f) + m_ai_info->max_delta_turn_rate = m_ai_max_turn_rate / m_ai_max_turn_rate_time; + else + m_ai_info->max_delta_turn_rate = 0.0f; + + m_ai_info->circle_distance = m_circle_distance; + m_ai_info->attack_vel_percent = m_attack_vel_percent/100.0; + m_ai_info->dodge_percent = m_dogde_percent/100.0; + m_ai_info->dodge_vel_percent = m_dodge_vel_percent/100.0; + m_ai_info->flee_vel_percent = m_flee_vel_percent/100.0; + m_ai_info->melee_damage[0] = m_melee1_distance; + m_ai_info->melee_damage[1] = m_melee2_distance; + m_ai_info->melee_latency[0] = m_melee1_latency; + m_ai_info->melee_latency[1] = m_melee2_latency; + m_ai_info->avoid_friends_distance = m_avoid_friends_dist; + + m_ai_info->biased_flight_min = m_bfhmin; + m_ai_info->biased_flight_max = m_bfhmax; + + m_ai_info->sound[AI_ANGRY_SOUND] = FindSoundName(m_angry_sound_combo.GetBuffer(0)); + m_ai_info->sound[AI_ATTACK_SOUND] = FindSoundName(m_attack_sound_combo.GetBuffer(0)); + m_ai_info->sound[AI_FLEE_SOUND] = FindSoundName(m_flee_sound_combo.GetBuffer(0)); + m_ai_info->sound[AI_SEE_SOUND] = FindSoundName(m_see_sound_combo.GetBuffer(0)); + m_ai_info->sound[AI_TURRET_SOUND] = FindSoundName(m_turret_sound_combo.GetBuffer(0)); + + m_ai_info->fire_spread = m_fire_spread_slider.GetPos()/(float)MAX_SLIDER_RANGE; + m_ai_info->night_vision = m_nv_slider.GetPos()/(float)MAX_SLIDER_RANGE; + m_ai_info->fog_vision = m_fv_slider.GetPos()/(float)MAX_SLIDER_RANGE; + m_ai_info->curiousity = m_curiousity_slider.GetPos()/(float)MAX_SLIDER_RANGE; + m_ai_info->lead_accuracy = m_tla_slider.GetPos()/(float)MAX_SLIDER_RANGE; + m_ai_info->lead_varience = m_tlv_slider.GetPos()/(float)MAX_SLIDER_RANGE; + m_ai_info->fight_team = m_fight_team_slider.GetPos()/(float)MAX_SLIDER_RANGE; + m_ai_info->fight_same = m_fight_same_slider.GetPos()/(float)MAX_SLIDER_RANGE; + m_ai_info->agression = m_agression_slider.GetPos()/(float)MAX_SLIDER_RANGE; + m_ai_info->hearing = m_hearing_slider.GetPos()/(float)MAX_SLIDER_RANGE; + m_ai_info->frustration = m_frustration_slider.GetPos()/(float)MAX_SLIDER_RANGE; + m_ai_info->roaming = m_roaming_slider.GetPos()/(float)MAX_SLIDER_RANGE; + m_ai_info->life_preservation = m_lp_slider.GetPos()/(float)MAX_SLIDER_RANGE; + m_ai_info->biased_flight_importance = m_bfhi_slider.GetPos()/(float)MAX_SLIDER_RANGE; +} diff --git a/editor/AISettingsDlg.h b/editor/AISettingsDlg.h new file mode 100644 index 00000000..786a386e --- /dev/null +++ b/editor/AISettingsDlg.h @@ -0,0 +1,133 @@ +#if !defined(AFX_AISETTINGSDLG_H__E93B3161_0DB4_11D1_86CC_004033312F7C__INCLUDED_) +#define AFX_AISETTINGSDLG_H__E93B3161_0DB4_11D1_86CC_004033312F7C__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// AISettingsDlg.h : header file +// + +#include "objinfo.h" + +///////////////////////////////////////////////////////////////////////////// +// CAISettingsDlg dialog + +class CAISettingsDlg : public CDialog +{ +// Construction +public: + CAISettingsDlg(t_ai_info *ai_info,CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CAISettingsDlg) + enum { IDD = IDD_AI }; + CSliderCtrl m_bfhi_slider; + CSliderCtrl m_tlv_slider; + CSliderCtrl m_tla_slider; + CSliderCtrl m_roaming_slider; + CSliderCtrl m_nv_slider; + CSliderCtrl m_lp_slider; + CSliderCtrl m_hearing_slider; + CSliderCtrl m_fv_slider; + CSliderCtrl m_frustration_slider; + CSliderCtrl m_fight_team_slider; + CSliderCtrl m_fight_same_slider; + CSliderCtrl m_curiousity_slider; + CSliderCtrl m_agression_slider; + CSliderCtrl m_fire_spread_slider; + BOOL m_fire_weapon1; + BOOL m_fire_weapon2; + BOOL m_melee1; + BOOL m_melee2; + BOOL m_stay_inout; + CString m_ai_class; + float m_ai_flock_alignment; + float m_ai_flock_cohesion; + BOOL m_ai_flock_member_check; + float m_ai_flock_seperation; + float m_ai_fov; + CString m_initial_action; + BOOL m_ai_uses_thrust_check; + CString m_ai_type; + CString m_ai_movement_type; + CString m_ai_movement_subtype; + float m_ai_max_velocity; + float m_ai_max_vel_time; + float m_ai_max_turn_rate; + BOOL m_dodge_check; + BOOL m_fireattarget_check; + BOOL m_flinch_check; + BOOL m_notify_hitbyweapon_check; + BOOL m_notify_nearwall_check; + BOOL m_notify_objectfired_check; + BOOL m_notify_seeplayer_check; + BOOL m_notify_weaponhittarget_check; + BOOL m_retarget_check; + BOOL m_turretcontrol_check; + BOOL m_tauntatdeath_check; + BOOL m_avoidwalls_check; + BOOL m_notify_hears_noise; + BOOL m_persistant_check; + BOOL m_fluctuate_speed_properties_check; + float m_ai_max_turn_rate_time; + CString m_angry_sound_combo; + CString m_attack_sound_combo; + float m_circle_distance; + float m_attack_vel_percent; + float m_dogde_percent; + float m_dodge_vel_percent; + CString m_flee_sound_combo; + float m_flee_vel_percent; + float m_melee1_latency; + float m_melee1_distance; + float m_melee2_distance; + float m_melee2_latency; + CString m_see_sound_combo; + BOOL m_ordered_wb_firing_check; + BOOL m_orient_to_vel; + BOOL m_xz_dist; + BOOL m_target_by_dist_check; + CString m_turret_sound_combo; + BOOL m_avoid_friends_check; + float m_avoid_friends_dist; + float m_bfhmax; + float m_bfhmin; + BOOL m_bfh_check; + BOOL m_fov_uvec; + BOOL m_fov_aim; + //}}AFX_DATA + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAISettingsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + //The data we're editing + t_ai_info *m_ai_info; + + // Generated message map functions + //{{AFX_MSG(CAISettingsDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeAiMovementTypeCombo(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +#include "objinfo.h" + +//Copy data from ai_info struct to CAISettingsDlg class +void CopyAIData(CAISettingsDlg *dlg,ai_frame *ai_info); + +//Copy data from CAISettingsDlg class to ai_info struct +void CopyAIData(ai_frame *ai_info,CAISettingsDlg *dlg); + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_AISETTINGSDLG_H__E93B3161_0DB4_11D1_86CC_004033312F7C__INCLUDED_) diff --git a/editor/AddScriptDialog.cpp b/editor/AddScriptDialog.cpp new file mode 100644 index 00000000..59e635d7 --- /dev/null +++ b/editor/AddScriptDialog.cpp @@ -0,0 +1,62 @@ +// AddScriptDialog.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "AddScriptDialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CAddScriptDialog dialog + + +CAddScriptDialog::CAddScriptDialog(CWnd* pParent /*=NULL*/) + : CDialog(CAddScriptDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CAddScriptDialog) + m_Name = _T(""); + m_TypeName = _T(""); + //}}AFX_DATA_INIT +} + + +void CAddScriptDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAddScriptDialog) + DDX_Text(pDX, IDC_EDITNAME, m_Name); + DDV_MaxChars(pDX, m_Name, 32); + DDX_CBString(pDX, IDC_TYPESEL, m_TypeName); + DDV_MaxChars(pDX, m_TypeName, 16); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CAddScriptDialog, CDialog) + //{{AFX_MSG_MAP(CAddScriptDialog) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CAddScriptDialog message handlers + + +BOOL CAddScriptDialog::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CComboBox *cbox = (CComboBox *)GetDlgItem(IDC_TYPESEL); + + cbox->AddString("object"); + cbox->AddString("trigger"); + cbox->SelectString(-1, "object"); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + diff --git a/editor/AddScriptDialog.h b/editor/AddScriptDialog.h new file mode 100644 index 00000000..f89f57b6 --- /dev/null +++ b/editor/AddScriptDialog.h @@ -0,0 +1,47 @@ +#if !defined(AFX_ADDSCRIPTDIALOG_H__A86E5781_3427_11D1_BDC3_00A0C96ED595__INCLUDED_) +#define AFX_ADDSCRIPTDIALOG_H__A86E5781_3427_11D1_BDC3_00A0C96ED595__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// AddScriptDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CAddScriptDialog dialog + +class CAddScriptDialog : public CDialog +{ +// Construction +public: + CAddScriptDialog(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CAddScriptDialog) + enum { IDD = IDD_ADDSCRIPT }; + CString m_Name; + CString m_TypeName; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAddScriptDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CAddScriptDialog) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_ADDSCRIPTDIALOG_H__A86E5781_3427_11D1_BDC3_00A0C96ED595__INCLUDED_) diff --git a/editor/AmbientSoundElement.cpp b/editor/AmbientSoundElement.cpp new file mode 100644 index 00000000..01b51d9f --- /dev/null +++ b/editor/AmbientSoundElement.cpp @@ -0,0 +1,92 @@ +// AmbientSoundElement.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "AmbientSoundElement.h" +#include "soundload.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CAmbientSoundElement dialog + + +CAmbientSoundElement::CAmbientSoundElement(ase *ase,CWnd* pParent /*=NULL*/) + : CDialog(CAmbientSoundElement::IDD, pParent) +{ + //{{AFX_DATA_INIT(CAmbientSoundElement) + m_min_volume = 0.0f; + m_max_volume = 0.0f; + m_probability = 0; + //}}AFX_DATA_INIT + + m_ase = ase; + + m_min_volume = ase->min_volume; + m_max_volume = ase->max_volume; + m_probability = ase->probability; + m_handle = ase->handle; +} + + +void CAmbientSoundElement::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAmbientSoundElement) + DDX_Text(pDX, IDC_MIN_VOLUME, m_min_volume); + DDX_Text(pDX, IDC_ASE_MAX_VOLUME, m_max_volume); + DDX_Text(pDX, IDC_ASE_PROBABILITY, m_probability); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CAmbientSoundElement, CDialog) + //{{AFX_MSG_MAP(CAmbientSoundElement) + ON_CBN_SELENDOK(IDC_ASE_SOUND_LIST, OnSelendokASESoundList) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CAmbientSoundElement message handlers + +void CAmbientSoundElement::OnOK() +{ + CDialog::OnOK(); + + m_ase->min_volume = m_min_volume; + m_ase->max_volume = m_max_volume; + m_ase->probability = m_probability; + m_ase->handle = m_handle; + +} + +#include "pserror.h" + +void CAmbientSoundElement::OnSelendokASESoundList() +{ + char name[200]; + CComboBox *soundlist = (CComboBox *) GetDlgItem(IDC_ASE_SOUND_LIST); + + soundlist->GetLBText(soundlist->GetCurSel(),name); + m_handle = FindSoundName(name); +} + +BOOL CAmbientSoundElement::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CComboBox *soundlist = (CComboBox *) GetDlgItem(IDC_ASE_SOUND_LIST); + soundlist->ResetContent(); + for (int i=0;iAddString(Sounds[i].name); + soundlist->SelectString(-1,Sounds[m_handle].name); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/editor/AmbientSoundElement.h b/editor/AmbientSoundElement.h new file mode 100644 index 00000000..bee1621a --- /dev/null +++ b/editor/AmbientSoundElement.h @@ -0,0 +1,58 @@ +#if !defined(AFX_AMBIENTSOUNDELEMENT_H__D3451742_3680_11D2_A13A_0060089A8026__INCLUDED_) +#define AFX_AMBIENTSOUNDELEMENT_H__D3451742_3680_11D2_A13A_0060089A8026__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// AmbientSoundElement.h : header file +// + +#include "ambient.h" + +///////////////////////////////////////////////////////////////////////////// +// CAmbientSoundElement dialog + +class CAmbientSoundElement : public CDialog +{ +// Construction +public: + CAmbientSoundElement(ase *ase,CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CAmbientSoundElement) + enum { IDD = IDD_AMBIENTSOUNDELEMENT }; + float m_min_volume; + float m_max_volume; + int m_probability; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAmbientSoundElement) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CAmbientSoundElement) + virtual void OnOK(); + afx_msg void OnSelendokASESoundList(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +private: + + ase *m_ase; + int m_handle; + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_AMBIENTSOUNDELEMENT_H__D3451742_3680_11D2_A13A_0060089A8026__INCLUDED_) diff --git a/editor/AmbientSoundPattern.cpp b/editor/AmbientSoundPattern.cpp new file mode 100644 index 00000000..5099c59b --- /dev/null +++ b/editor/AmbientSoundPattern.cpp @@ -0,0 +1,557 @@ +// AmbientSoundPattern.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "AmbientSoundPattern.h" +#include "AmbientSoundElement.h" +#include "EditLineDialog.h" +#include "ambient.h" +#include "ssl_lib.h" +#include "pserror.h" +#include "gamefilepage.h" +#include "ddio.h" +#include "mem.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CAmbientSoundPattern dialog + + +CAmbientSoundPattern::CAmbientSoundPattern(CWnd* pParent /*=NULL*/) + : CDialog(CAmbientSoundPattern::IDD, pParent) +{ + //{{AFX_DATA_INIT(CAmbientSoundPattern) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CAmbientSoundPattern::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAmbientSoundPattern) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CAmbientSoundPattern, CDialog) + //{{AFX_MSG_MAP(CAmbientSoundPattern) + ON_CBN_SELENDOK(IDC_ASP_LIST, OnSelendokASPList) + ON_BN_CLICKED(IDC_ASP_CHECK_IN, OnASPCheckIn) + ON_BN_CLICKED(IDC_ASP_DELETE, OnASPDelete) + ON_BN_CLICKED(IDC_ASP_EDIT_ELEMENT, OnASPEditElement) + ON_BN_CLICKED(IDC_ASP_LOCK, OnASPLock) + ON_BN_CLICKED(IDC_ASP_NEW, OnASPNew) + ON_BN_CLICKED(IDC_ASP_NEW_ELEMENT, OnASPNewElement) + ON_BN_CLICKED(IDC_ASP_RENAME, OnASPRename) + ON_LBN_SELCHANGE(IDC_ASP_ELEMENT_LIST, OnSelchangeASPElementList) + ON_BN_CLICKED(IDC_ASP_DELETE_ELEMENT, OnASPDeleteElement) + ON_BN_CLICKED(IDC_ASP_UNDO_LOCK, OnASPUndoLock) + ON_EN_KILLFOCUS(IDC_ASP_MAX_DELAY, OnKillfocusASPMaxDelay) + ON_EN_KILLFOCUS(IDC_ASP_MIN_DELAY, OnKillfocusASPMinDelay) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CAmbientSoundPattern message handlers + +BOOL CAmbientSoundPattern::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_current_asp = m_current_element = -1; + + m_locked = (mng_FindTrackLock(AMBIENT_FILE_NAME,PAGETYPE_GAMEFILE) != -1); + + UpdateDialog(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CAmbientSoundPattern::UpdateDialog() +{ + int i; + + //Build the ambient sound list + CComboBox *asplist = (CComboBox *) GetDlgItem(IDC_ASP_LIST); + asplist->ResetContent(); + for (i=0;iAddString(Ambient_sound_patterns[i].name); + if (m_current_asp == -1) + m_current_asp = i; + } + if (m_current_asp != -1) + asplist->SelectString(-1,Ambient_sound_patterns[m_current_asp].name); + + //Write out elements for current ASP + CListBox *aselist = (CListBox *)GetDlgItem(IDC_ASP_ELEMENT_LIST); + char tbuf[100]; + asp *asp = &Ambient_sound_patterns[m_current_asp]; + aselist->ResetContent(); + for (i=0;inum_sounds;i++) { + ase *ase = &asp->sounds[i]; + sprintf(tbuf,"%s: vol=%.2f,%.2f prob=%d",Sounds[ase->handle].name,ase->min_volume,ase->max_volume,ase->probability); + aselist->AddString(tbuf); + } + + //Write out the delay values + CEdit *ebox = (CEdit *) GetDlgItem(IDC_ASP_MIN_DELAY); + char buf[20]; + sprintf (buf,"%.1f",asp->min_delay); + ebox->SetWindowText(buf); + + ebox = (CEdit *) GetDlgItem(IDC_ASP_MAX_DELAY); + sprintf (buf,"%.1f",asp->max_delay); + ebox->SetWindowText(buf); + + //Select current element + if (aselist->GetCount() > 0) + aselist->SetCurSel(m_current_element); + + //Enable/disable editing buttons + ((CButton *)GetDlgItem(IDC_ASP_DELETE))->EnableWindow(m_locked); + ((CButton *)GetDlgItem(IDC_ASP_EDIT_ELEMENT))->EnableWindow(m_locked); + ((CButton *)GetDlgItem(IDC_ASP_NEW))->EnableWindow(m_locked); + ((CButton *)GetDlgItem(IDC_ASP_NEW_ELEMENT))->EnableWindow(m_locked); + ((CButton *)GetDlgItem(IDC_ASP_RENAME))->EnableWindow(m_locked); + ((CButton *)GetDlgItem(IDC_ASP_DELETE_ELEMENT))->EnableWindow(m_locked); + ((CButton *)GetDlgItem(IDC_ASP_MIN_DELAY))->EnableWindow(m_locked); + ((CButton *)GetDlgItem(IDC_ASP_MAX_DELAY))->EnableWindow(m_locked); + + //Enable/disable locking buttons + ((CButton *)GetDlgItem(IDC_ASP_CHECK_IN))->EnableWindow(m_locked); + ((CButton *)GetDlgItem(IDC_ASP_UNDO_LOCK))->EnableWindow(m_locked); + ((CButton *)GetDlgItem(IDC_ASP_LOCK))->EnableWindow(!m_locked); +} + +void CAmbientSoundPattern::OnSelendokASPList() +{ + char name[200]; + + CComboBox *asplist = (CComboBox *) GetDlgItem(IDC_ASP_LIST); + + asplist->GetLBText(asplist->GetCurSel(), name); + m_current_asp = FindAmbientSoundPattern(name); + + if (Ambient_sound_patterns[m_current_asp].num_sounds) + m_current_element = 0; + else + m_current_element = -1; + + UpdateDialog(); +} + + +void CAmbientSoundPattern::OnASPRename() +{ + if (! InputString(Ambient_sound_patterns[m_current_asp].name,sizeof(Ambient_sound_patterns[m_current_asp].name),"Ambient Sound Pattern","Enter a new name")) + return; + + UpdateDialog(); +} + +void CAmbientSoundPattern::OnSelchangeASPElementList() +{ + CListBox *lb = (CListBox *)GetDlgItem(IDC_ASP_ELEMENT_LIST); + + m_current_element = lb->GetCurSel(); +} + +void CAmbientSoundPattern::OnASPDelete() +{ + if (OutrageMessageBox(MBOX_YESNO,"Do you really want to delete the ambient sound pattern '%s'?",AmbientSoundPatternName(m_current_asp)) == IDYES) { + asp *asp = &Ambient_sound_patterns[m_current_asp]; + + asp->name[0] = 0; //null string for name + mem_free(asp->sounds); + asp->num_sounds = 0; + m_current_asp = -1; + + UpdateDialog(); + } +} + +void CAmbientSoundPattern::OnASPNew() +{ + asp *asp = &Ambient_sound_patterns[Num_ambient_sound_patterns]; + + if (InputString(asp->name,sizeof(asp->name),"Ambient Sound Pattern","Enter a name for your new pattern")) + if (asp->name[0]) { + asp->num_sounds = 0; + asp->min_delay = asp->max_delay = 0.0; + m_current_asp = Num_ambient_sound_patterns++; + UpdateDialog(); + } +} + +void CAmbientSoundPattern::OnASPNewElement() +{ + asp *asp = &Ambient_sound_patterns[m_current_asp]; + ase new_element; + + new_element.handle = -1; + new_element.min_volume = new_element.max_volume = 1.0; + new_element.probability = 50; + + CAmbientSoundElement dlg(&new_element); + + theApp.pause(); + dlg.DoModal(); + theApp.resume(); + + if (new_element.handle != -1) { + + ase *new_sounds = (ase *) mem_malloc(sizeof(*new_sounds) * (asp->num_sounds+1)); + + for (int s=0;snum_sounds;s++) + new_sounds[s] = asp->sounds[s]; + + mem_free(asp->sounds); + + asp->sounds = new_sounds; + asp->sounds[s] = new_element; + + asp->num_sounds++; + + m_current_element = s; + + UpdateDialog(); + } +} + + +void CAmbientSoundPattern::OnASPEditElement() +{ + if (m_current_element > -1) { + CAmbientSoundElement dlg(&Ambient_sound_patterns[m_current_asp].sounds[m_current_element]); + + theApp.pause(); + dlg.DoModal(); + theApp.resume(); + + UpdateDialog(); + } +} + +void CAmbientSoundPattern::OnASPDeleteElement() +{ + asp *asp = &Ambient_sound_patterns[m_current_asp]; + ase *new_sounds; + + if (m_current_element > -1) { + if (OutrageMessageBox(MBOX_YESNO,"Do you really want to delete sound '%s' from pattern '%s'?",Sounds[asp->sounds[m_current_element].handle].name,asp->name) == IDYES) { + new_sounds = (ase *) mem_malloc(sizeof(*new_sounds) * (asp->num_sounds-1)); + + for (int s=0;ssounds[s]; + + for (;snum_sounds-1;s++) + new_sounds[s] = asp->sounds[s+1]; + + mem_free(asp->sounds); + + asp->sounds = new_sounds; + + asp->num_sounds--; + + UpdateDialog(); + } + } +} + + +void CAmbientSoundPattern::OnKillfocusASPMinDelay() +{ + asp *asp = &Ambient_sound_patterns[m_current_asp]; + + CEdit *ebox; + char buf[20]; + + ebox = (CEdit *) GetDlgItem(IDC_ASP_MIN_DELAY); + ebox->GetWindowText(buf,sizeof(buf)); + + asp->min_delay = atof(buf); + + UpdateDialog(); +} + +void CAmbientSoundPattern::OnKillfocusASPMaxDelay() +{ + asp *asp = &Ambient_sound_patterns[m_current_asp]; + + CEdit *ebox; + char buf[20]; + + ebox = (CEdit *) GetDlgItem(IDC_ASP_MAX_DELAY); + ebox->GetWindowText(buf,sizeof(buf)); + + asp->max_delay = atof(buf); + + UpdateDialog(); +} + +void CAmbientSoundPattern::OnCancel() +{ + //Re-read old data + ReadAmbientData(); + + CDialog::OnCancel(); +} + +void CAmbientSoundPattern::OnOK() +{ + //Verify probabilities + for (int p=0;pnum_sounds) { + int prob=0; + + for (int s=0;snum_sounds;s++) + prob += asp->sounds[s].probability; + + if (prob != 100) { + OutrageMessageBox("Error: the probabilities for pattern '%s' don't add up to 100.",asp->name); + return; + } + } + } + + //Update the data + WriteAmbientData(); + + CDialog::OnOK(); +} + + +void CAmbientSoundPattern::OnASPLock() +{ + int n; + mngs_Pagelock temp_pl; + mngs_gamefile_page gamefilepage; + int r; + + // Find where it is in the list + n=FindGamefileName (AMBIENT_FILE_NAME); + + if (n==-1) + { + Int3(); // Get Matt or Jason - AMBIENT file name is no longer in the table file! + return; + } + + if (!mng_MakeLocker()) + return; + + // Make sure it can be locked + strcpy (temp_pl.name,AMBIENT_FILE_NAME); + temp_pl.pagetype=PAGETYPE_GAMEFILE; + + r=mng_CheckIfPageLocked (&temp_pl); + if (r==2) + { + int answer; + answer=OutrageMessageBox (MBOX_YESNO, "This page is not even in the table file, or the database maybe corrupt. Override to 'Unlocked'? (Select NO if you don't know what you're doing)"); + if (answer==IDYES) + { + strcpy (temp_pl.holder,"UNLOCKED"); + if (!mng_ReplacePagelock (temp_pl.name,&temp_pl)) + MessageBox (ErrorString,"Error!"); + + } + } + else if (r<0) + OutrageMessageBox (ErrorString); + else if (r==1) + OutrageMessageBox (InfoString); + else + { + + // Everything is ok. Tell the network we're locking it and get a copy to + // our local drive + strcpy (temp_pl.holder,TableUser); + + // Search thru the net pagefile and get a new copy in RAM in case anyone + // changed it since we started the editor + if ( mng_FindSpecificGamefilePage (temp_pl.name,&gamefilepage,0)) + { + + if (mng_AssignGamefilePageToGamefile (&gamefilepage,n)) + { + if (!mng_ReplacePage (Gamefiles[n].name,Gamefiles[n].name,n,PAGETYPE_GAMEFILE,1)) + { + OutrageMessageBox ("There was problem writing that page locally!"); + mng_EraseLocker(); + return; + } + else + { + + if (!mng_ReplacePagelock (temp_pl.name,&temp_pl)) + { + MessageBox (ErrorString,"Error!"); + mng_EraseLocker(); + return; + } + } + OutrageMessageBox ("Gamefile locked."); + } + else + OutrageMessageBox ("There was a problem loading this gamefile. You might encounter problems in dealing with it. Good luck!"); + + mng_AllocTrackLock(Gamefiles[n].name,PAGETYPE_GAMEFILE); + UpdateDialog (); + } + else + OutrageMessageBox ("Couldn't find that gamefile in the table file!"); + } + + mng_EraseLocker(); + + //Read the data again in case we just got a newer file + ReadAmbientData(); + + m_locked = 1; + + UpdateDialog(); +} + +void CAmbientSoundPattern::OnASPCheckIn() +{ + //Write the updated data to the file + WriteAmbientData(); + + // Find where it is in the files index + int n=FindGamefileName (AMBIENT_FILE_NAME); + + if (n==-1) + { + Int3(); // Get Matt or Jason - AMBIENT file name is no longer in the table file! + return; + } + + mngs_Pagelock temp_pl; + int r; + + // Lock the network table file + if (!mng_MakeLocker()) + return; + + // Make sure we own this gamefile + strcpy (temp_pl.name,Gamefiles[n].name); + temp_pl.pagetype=PAGETYPE_GAMEFILE; + + r=mng_CheckIfPageOwned (&temp_pl,TableUser); + if (r<0) + OutrageMessageBox (ErrorString); + else if (r==0) + OutrageMessageBox (InfoString); + else + { + // Change the pagelock state to UNLOCKED + strcpy (temp_pl.holder,"UNLOCKED"); + if (!mng_ReplacePagelock (temp_pl.name,&temp_pl)) + { + MessageBox (ErrorString,"Error!"); + mng_EraseLocker(); + return; + } + else + { + // Now actually replace the copy on the net with our local one + + if (!mng_ReplacePage (Gamefiles[n].name,Gamefiles[n].name,n,PAGETYPE_GAMEFILE,0)) + OutrageMessageBox (ErrorString); + else + { + // Save this gamefile file to the network for all + + char destname[100],srcname[100]; + + ddio_MakePath(srcname,LocalD3Dir,"data",Gamefiles[n].dir_name,Gamefiles[n].name,NULL); + ddio_MakePath(destname,NetD3Dir,"data",Gamefiles[n].dir_name,Gamefiles[n].name,NULL); + + cf_CopyFile (destname,srcname); + + OutrageMessageBox ("File checked in."); + + // Delete it from local pagefile if its there + int dret=mng_DeletePage (Gamefiles[n].name,PAGETYPE_GAMEFILE,1); + ASSERT (dret==1); + mng_EraseLocker(); + + // Free the tracklock + int p=mng_FindTrackLock (Gamefiles[n].name,PAGETYPE_GAMEFILE); + ASSERT (p!=-1); + mng_FreeTrackLock (p); + } + } + } + + m_locked = 0; + UpdateDialog(); +} + +void CAmbientSoundPattern::OnASPUndoLock() +{ + int tl; + mngs_Pagelock pl; + mngs_gamefile_page page; + + //Should have this item locked + if ((tl=mng_FindTrackLock (AMBIENT_FILE_NAME,PAGETYPE_GAMEFILE))==-1) + return; + + if (OutrageMessageBox(MBOX_YESNO,"Are you sure you want to undo your lock and lose any changes you may have made?") != IDYES) + return; + + if (!mng_MakeLocker()) + return; + + // Find where it is in the files index + int n=FindGamefileName (AMBIENT_FILE_NAME); + + if (n==-1) + { + Int3(); // Get Matt or Jason - AMBIENT file name is no longer in the table file! + return; + } + + strcpy (pl.name,AMBIENT_FILE_NAME); + pl.pagetype=PAGETYPE_GAMEFILE; + + mng_FreeTrackLock (tl); + + //Delete local page + if (!mng_DeletePage (AMBIENT_FILE_NAME,PAGETYPE_GAMEFILE,1)) { + mprintf ((0,ErrorString)); + Int3(); + } + + //Get old data from net + if (! mng_FindSpecificGamefilePage(pl.name,&page)) + Int3(); + + //Copy old get into our local array + if (! mng_AssignGamefilePageToGamefile (&page,n)) + Int3(); + + //We're done + mng_EraseLocker(); + + //Re-read old data + ReadAmbientData(); + + m_current_asp = -1; + m_locked = 0; + + UpdateDialog(); +} diff --git a/editor/AmbientSoundPattern.h b/editor/AmbientSoundPattern.h new file mode 100644 index 00000000..8356f3eb --- /dev/null +++ b/editor/AmbientSoundPattern.h @@ -0,0 +1,69 @@ +#if !defined(AFX_AMBIENTSOUNDPATTERN_H__D3451741_3680_11D2_A13A_0060089A8026__INCLUDED_) +#define AFX_AMBIENTSOUNDPATTERN_H__D3451741_3680_11D2_A13A_0060089A8026__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// AmbientSoundPattern.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CAmbientSoundPattern dialog + +class CAmbientSoundPattern : public CDialog +{ +// Construction +public: + CAmbientSoundPattern(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CAmbientSoundPattern) + enum { IDD = IDD_AMBIENTSOUNDPATTERNS }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAmbientSoundPattern) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CAmbientSoundPattern) + virtual BOOL OnInitDialog(); + afx_msg void OnSelendokASPList(); + afx_msg void OnASPCheckIn(); + afx_msg void OnASPDelete(); + afx_msg void OnASPEditElement(); + afx_msg void OnASPLock(); + afx_msg void OnASPNew(); + afx_msg void OnASPNewElement(); + afx_msg void OnASPRename(); + afx_msg void OnSelchangeASPElementList(); + afx_msg void OnASPDeleteElement(); + virtual void OnCancel(); + virtual void OnOK(); + afx_msg void OnASPUndoLock(); + afx_msg void OnKillfocusASPMaxDelay(); + afx_msg void OnKillfocusASPMinDelay(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +private: + void UpdateDialog(); + + bool m_locked; + int m_current_asp; + int m_current_element; + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_AMBIENTSOUNDPATTERN_H__D3451741_3680_11D2_A13A_0060089A8026__INCLUDED_) diff --git a/editor/AnimStatesDialog.cpp b/editor/AnimStatesDialog.cpp new file mode 100644 index 00000000..23791f1a --- /dev/null +++ b/editor/AnimStatesDialog.cpp @@ -0,0 +1,1398 @@ +/* + * $Logfile: /DescentIII/Main/editor/AnimStatesDialog.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:57:37 $ + * $Author: kevinb $ + * + * AnimStatesDialog.cpp : implementation file + * + * $Log: not supported by cvs2svn $ + * + * 17 10/22/99 6:04p Jeff + * fixed bugs and compiler errors resulting from mac code merge + * + * 16 9/21/99 5:06p Chris + * Faster animation dialog updates - an editor ONLY change + * + * 15 6/15/98 4:00p Jason + * replaced monochromatic polymodel lighting with rgb lighting + * + * 14 5/03/98 5:38p Chris + * Added sounds to anim page + * + * 13 4/16/98 2:56p Chris + * Added birth Animation + * + * 12 4/13/98 2:20p Chris + * IDLe works (kindof) + * + * 11 4/02/98 3:54p Jason + * first pass in getting polymodel paging to work + * + * 10 2/16/98 2:49p Chris + * Made the MAX_SUBOBJECTS determine the number of normalized_time values + * to be processed. No longer a 'literal' problem. + * + * 9 2/16/98 2:47a Chris + * Massive improvements to the animation system and the AI + * + * 8 12/19/97 11:25a Samir + * g3_StartFrame and g3_EndFrame replaced by EditorStartFrame and + * EditorEndFrame + * + * 7 12/17/97 3:17p Jason + * fixed potential fabs/abs bug + * + * 6 10/05/97 5:30a Chris + * Added more support for TIMED animations + * + * 5 9/08/97 11:51a Chris + * Added support for entering seconds-per-cycle animation information + * + * 4 8/08/97 11:45a Matt + * Made anim states dialog keep local copy of anim array. The caller then + * copies the data to his own array if the user exits from the dialog via + * OK. + * + * 3 8/06/97 1:35p Matt + * Changes for new generic object_info struct which replace robot-specific + * structure + * + * 2 7/24/97 6:35p Matt + * Created symbolic constant for default zoom, and used it every place + * that specifies zoom + * + * $NoKeywords: $ + */ + +#include "stdafx.h" +#include "editor.h" +#include "AnimStatesDialog.h" +#include "polymodel.h" +#include "gr.h" +#include "soundpage.h" +#include "soundload.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CAnimStatesDialog dialog + + +CAnimStatesDialog::CAnimStatesDialog(int render_handle,anim_elem *anim_info,CWnd* pParent /*=NULL*/) + : CDialog(CAnimStatesDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CAnimStatesDialog) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + m_render_handle = render_handle; + + for (int i=0;iGetWindowRect(&rect); + ScreenToClient(&rect); + + Desktop_surf->attach_to_window((unsigned)m_hWnd); + + w=rect.right-rect.left; + h=rect.bottom-rect.top; + + bm_handle = m_render_handle; //GetObjectImage(m_current_id); + + vector zero_vector; + vector view_vector={0,0,-20}; + matrix id_matrix,rot_matrix; + poly_model *pm=GetPolymodelPointer (bm_handle); + + vm_MakeZero (&zero_vector); + vm_MakeIdentity (&id_matrix); + + float norm_angles[MAX_SUBOBJECTS]; + float keyframe = frame_start + frame_diff*((float)frame/(float)NUM_ANIM_FRAMES); + + SetNormalizedTimeAnim(keyframe, norm_angles, pm); + + vm_AnglesToMatrix (&rot_matrix,0,m_SpinFrame*400,0); + view_vector.z=-(fabs(pm->maxs.z-pm->mins.z)*2); + + surf.create(128, 128, BPP_16); + grViewport *vport=new grViewport (&surf); + StartEditorFrame (vport,&view_vector,&id_matrix,D3_DEFAULT_ZOOM); + DrawPolygonModel (&zero_vector,&rot_matrix,bm_handle,norm_angles,0,1.0,1.0,1.0); + EndEditorFrame(); + + x = rect.left + ((rect.right-rect.left)/2) - surf.width()/2; + y = rect.top + ((rect.bottom-rect.top)/2) - surf.height()/2; + Desktop_surf->blt(x, y, &surf); + + delete vport; + surf.free(); + + +} + + +void CAnimStatesDialog::UpdateDialog() +{ + CEdit *ebox; + char str[20]; + int mc=m_current_state; + int max_states=24; + int control_froms[]={IDC_ALERT_FROM_EDIT,IDC_DEATH_FROM_EDIT,IDC_MISSILE1_FROM_EDIT, + IDC_RECOIL1_FROM_EDIT, IDC_MISSILE2_FROM_EDIT, + IDC_RECOIL2_FROM_EDIT,IDC_MELEE1_FROM_EDIT,IDC_MRECOIL1_FROM_EDIT, + IDC_MELEE2_FROM_EDIT,IDC_MRECOIL2_FROM_EDIT,IDC_IDLE_FROM_EDIT, + IDC_QUIRK_FROM_EDIT,IDC_FLINCH_FROM_EDIT,IDC_TAUNT_FROM_EDIT, + IDC_SPECIAL1_FROM_EDIT,IDC_SPECIAL2_FROM_EDIT,IDC_SPECIAL3_FROM_EDIT, + IDC_SPECIAL4_FROM_EDIT,IDC_SPECIAL5_FROM_EDIT, + IDC_STANDING_FROM_EDIT,IDC_FLYING_FROM_EDIT,IDC_ROLLING_FROM_EDIT, + IDC_WALKING_FROM_EDIT,IDC_JUMPING_FROM_EDIT}; + + + int control_tos[]= {IDC_ALERT_TO_EDIT,IDC_DEATH_TO_EDIT,IDC_MISSILE1_TO_EDIT, + IDC_RECOIL1_TO_EDIT, IDC_MISSILE2_TO_EDIT, + IDC_RECOIL2_TO_EDIT,IDC_MELEE1_TO_EDIT,IDC_MRECOIL1_TO_EDIT, + IDC_MELEE2_TO_EDIT,IDC_MRECOIL2_TO_EDIT,IDC_IDLE_TO_EDIT, + IDC_QUIRK_TO_EDIT,IDC_FLINCH_TO_EDIT,IDC_TAUNT_TO_EDIT, + IDC_SPECIAL1_TO_EDIT,IDC_SPECIAL2_TO_EDIT,IDC_SPECIAL3_TO_EDIT, + IDC_SPECIAL4_TO_EDIT,IDC_SPECIAL5_TO_EDIT, + IDC_STANDING_TO_EDIT,IDC_FLYING_TO_EDIT,IDC_ROLLING_TO_EDIT, + IDC_WALKING_TO_EDIT,IDC_JUMPING_TO_EDIT}; + + int control_spc[]= {IDC_SEC_PER_CYCLE_EDIT1, IDC_SEC_PER_CYCLE_EDIT2, IDC_SEC_PER_CYCLE_EDIT3, + IDC_SEC_PER_CYCLE_EDIT4, IDC_SEC_PER_CYCLE_EDIT5, IDC_SEC_PER_CYCLE_EDIT6, + IDC_SEC_PER_CYCLE_EDIT7, IDC_SEC_PER_CYCLE_EDIT8, IDC_SEC_PER_CYCLE_EDIT9, + IDC_SEC_PER_CYCLE_EDIT10, IDC_SEC_PER_CYCLE_EDIT11, IDC_SEC_PER_CYCLE_EDIT12, + IDC_SEC_PER_CYCLE_EDIT13, IDC_SEC_PER_CYCLE_EDIT14, IDC_SEC_PER_CYCLE_EDIT15, + IDC_SEC_PER_CYCLE_EDIT16, IDC_SEC_PER_CYCLE_EDIT17, IDC_SEC_PER_CYCLE_EDIT18, + IDC_SEC_PER_CYCLE_EDIT19, IDC_SEC_PER_CYCLE_EDIT20, IDC_SEC_PER_CYCLE_EDIT21, + IDC_SEC_PER_CYCLE_EDIT22, IDC_SEC_PER_CYCLE_EDIT23, IDC_SEC_PER_CYCLE_EDIT24}; + + int anim_sounds[]= {IDC_ANIM_SOUND0_PULLDOWN, IDC_ANIM_SOUND1_PULLDOWN, IDC_ANIM_SOUND2_PULLDOWN, + IDC_ANIM_SOUND3_PULLDOWN, IDC_ANIM_SOUND4_PULLDOWN, IDC_ANIM_SOUND5_PULLDOWN, + IDC_ANIM_SOUND6_PULLDOWN, IDC_ANIM_SOUND7_PULLDOWN, IDC_ANIM_SOUND8_PULLDOWN, + IDC_ANIM_SOUND9_PULLDOWN, IDC_ANIM_SOUND10_PULLDOWN, IDC_ANIM_SOUND11_PULLDOWN, + IDC_ANIM_SOUND12_PULLDOWN, IDC_ANIM_SOUND13_PULLDOWN, IDC_ANIM_SOUND14_PULLDOWN, + IDC_ANIM_SOUND15_PULLDOWN, IDC_ANIM_SOUND16_PULLDOWN, IDC_ANIM_SOUND17_PULLDOWN, + IDC_ANIM_SOUND18_PULLDOWN, IDC_ANIM_SOUND19_PULLDOWN, IDC_ANIM_SOUND20_PULLDOWN, + IDC_ANIM_SOUND21_PULLDOWN, IDC_ANIM_SOUND22_PULLDOWN, IDC_ANIM_SOUND23_PULLDOWN}; + + CheckDlgButton (IDC_ALERT_CHECK,m_anim[mc].elem[AS_ALERT].used?1:0); + CheckDlgButton (IDC_DEATH_CHECK,m_anim[mc].elem[AS_DEATH].used?1:0); + CheckDlgButton (IDC_MISSILE1_CHECK,m_anim[mc].elem[AS_BIRTH].used?1:0); + CheckDlgButton (IDC_MISSILE1_RECOIL_CHECK,m_anim[mc].elem[AS_MISSILE1_RECOIL].used?1:0); + CheckDlgButton (IDC_MISSILE2_CHECK,m_anim[mc].elem[AS_MISSILE2].used?1:0); + CheckDlgButton (IDC_MISSILE2_RECOIL_CHECK,m_anim[mc].elem[AS_MISSILE2_RECOIL].used?1:0); + CheckDlgButton (IDC_MELEE1_CHECK,m_anim[mc].elem[AS_MELEE1].used?1:0); + CheckDlgButton (IDC_MELEE1_RECOIL_CHECK,m_anim[mc].elem[AS_MELEE1_RECOIL].used?1:0); + CheckDlgButton (IDC_MELEE2_CHECK,m_anim[mc].elem[AS_MELEE2].used?1:0); + CheckDlgButton (IDC_MELEE2_RECOIL_CHECK,m_anim[mc].elem[AS_MELEE2_RECOIL].used?1:0); + CheckDlgButton (IDC_QUIRK_CHECK,m_anim[mc].elem[AS_QUIRK].used?1:0); + CheckDlgButton (IDC_IDLE_CHECK,m_anim[mc].elem[AS_IDLE].used?1:0); + CheckDlgButton (IDC_TAUNT_CHECK,m_anim[mc].elem[AS_TAUNT].used?1:0); + CheckDlgButton (IDC_FLINCH_CHECK,m_anim[mc].elem[AS_FLINCH].used?1:0); + CheckDlgButton (IDC_SPECIAL1_CHECK,m_anim[mc].elem[AS_GOTO_IDLE_STANDING].used?1:0); + CheckDlgButton (IDC_SPECIAL2_CHECK,m_anim[mc].elem[AS_GOTO_IDLE_FLYING].used?1:0); + CheckDlgButton (IDC_SPECIAL3_CHECK,m_anim[mc].elem[AS_GOTO_IDLE_ROLLING].used?1:0); + CheckDlgButton (IDC_SPECIAL4_CHECK,m_anim[mc].elem[AS_GOTO_IDLE_WALKING].used?1:0); + CheckDlgButton (IDC_SPECIAL5_CHECK,m_anim[mc].elem[AS_GOTO_IDLE_JUMPING].used?1:0); + CheckDlgButton (IDC_GOTO_STANDING_CHECK,m_anim[mc].elem[AS_GOTO_ALERT_STANDING].used?1:0); + CheckDlgButton (IDC_GOTO_FLYING_CHECK,m_anim[mc].elem[AS_GOTO_ALERT_FLYING].used?1:0); + CheckDlgButton (IDC_GOTO_WALKING_CHECK,m_anim[mc].elem[AS_GOTO_ALERT_WALKING].used?1:0); + CheckDlgButton (IDC_GOTO_ROLLING_CHECK,m_anim[mc].elem[AS_GOTO_ALERT_ROLLING].used?1:0); + CheckDlgButton (IDC_GOTO_JUMPING_CHECK,m_anim[mc].elem[AS_GOTO_ALERT_JUMPING].used?1:0); + + + for (int i=0;iSetWindowText (str); + + ebox=(CEdit *) GetDlgItem (control_tos[i]); + itoa (m_anim[mc].elem[i].to,str,10); + ebox->SetWindowText (str); + + ebox=(CEdit *) GetDlgItem (control_spc[i]); + sprintf(str, "%f", m_anim[mc].elem[i].spc); + ebox->SetWindowText (str); + } + + if(!m_setup_sound_dialogs) + { + m_setup_sound_dialogs = true; + + for (i=0;i= 0 && m_anim[mc].elem[i].anim_sound_index < MAX_SOUNDS && Sounds[m_anim[mc].elem[i].anim_sound_index].used != 0) + SendDlgItemMessage( anim_sounds[i], CB_SELECTSTRING,0,(LPARAM) (LPCTSTR) Sounds[m_anim[mc].elem[i].anim_sound_index].name); + else + SendDlgItemMessage( anim_sounds[i], CB_SELECTSTRING,0,(LPARAM) (LPCTSTR) "\0"); + } + + SendDlgItemMessage( IDC_CURRENT_STATE_PULLDOWN, CB_RESETCONTENT,0,0); + for (i=0;iGetWindowText (str,20); + + int frame=atoi (str); + + if (framemax_keyframe) + frame=max_keyframe; + + m_anim[mc].elem[anim_state].from=frame; + UpdateDialog(); +} + +void CAnimStatesDialog::KillFocusSPC(int num) +{ + int control_spc[]= {IDC_SEC_PER_CYCLE_EDIT1, IDC_SEC_PER_CYCLE_EDIT2, IDC_SEC_PER_CYCLE_EDIT3, + IDC_SEC_PER_CYCLE_EDIT4, IDC_SEC_PER_CYCLE_EDIT5, IDC_SEC_PER_CYCLE_EDIT6, + IDC_SEC_PER_CYCLE_EDIT7, IDC_SEC_PER_CYCLE_EDIT8, IDC_SEC_PER_CYCLE_EDIT9, + IDC_SEC_PER_CYCLE_EDIT10, IDC_SEC_PER_CYCLE_EDIT11, IDC_SEC_PER_CYCLE_EDIT12, + IDC_SEC_PER_CYCLE_EDIT13, IDC_SEC_PER_CYCLE_EDIT14, IDC_SEC_PER_CYCLE_EDIT15, + IDC_SEC_PER_CYCLE_EDIT16, IDC_SEC_PER_CYCLE_EDIT17, IDC_SEC_PER_CYCLE_EDIT18, + IDC_SEC_PER_CYCLE_EDIT19, IDC_SEC_PER_CYCLE_EDIT20, IDC_SEC_PER_CYCLE_EDIT21, + IDC_SEC_PER_CYCLE_EDIT22, IDC_SEC_PER_CYCLE_EDIT23, IDC_SEC_PER_CYCLE_EDIT24}; + char str[20]; + int mc=m_current_state; + int i; + int max_states=24; + + // Find the index into the array + for (i = 0;i < max_states; i++) + if (control_spc[i] == num) + break; + + // Make sure that we find it + ASSERT (i != max_states); + + int anim_state = i; + + CEdit *ebox=(CEdit *) GetDlgItem (num); + ebox->GetWindowText (str,20); + + float spc = atof(str); + + if (spc <= 0.0 || spc >= 10000.0) + spc = 1.0f; + + m_anim[mc].elem[anim_state].spc = spc; + UpdateDialog(); +} + +void CAnimStatesDialog::KillFocusTos(int num) +{ + int control_tos[]={ IDC_ALERT_TO_EDIT,IDC_DEATH_TO_EDIT,IDC_MISSILE1_TO_EDIT, + IDC_RECOIL1_TO_EDIT, IDC_MISSILE2_TO_EDIT, + IDC_RECOIL2_TO_EDIT,IDC_MELEE1_TO_EDIT,IDC_MRECOIL1_TO_EDIT, + IDC_MELEE2_TO_EDIT,IDC_MRECOIL2_TO_EDIT,IDC_IDLE_TO_EDIT, + IDC_QUIRK_TO_EDIT,IDC_FLINCH_TO_EDIT,IDC_TAUNT_TO_EDIT, + IDC_SPECIAL1_TO_EDIT,IDC_SPECIAL2_TO_EDIT,IDC_SPECIAL3_TO_EDIT, + IDC_SPECIAL4_TO_EDIT,IDC_SPECIAL5_TO_EDIT, + IDC_STANDING_TO_EDIT,IDC_FLYING_TO_EDIT,IDC_ROLLING_TO_EDIT, + IDC_WALKING_TO_EDIT,IDC_JUMPING_TO_EDIT}; + + char str[20]; + int mc=m_current_state; + int min_keyframe = Poly_models[m_render_handle].frame_min; + int max_keyframe = Poly_models[m_render_handle].frame_max; + int i; + int max_states=24; + + for (i=0;iGetWindowText (str,20); + + int frame=atoi (str); + + if (framemax_keyframe) + frame=max_keyframe; + + + m_anim[mc].elem[anim_state].to=frame; + UpdateDialog(); +} + + +void CAnimStatesDialog::OnKillfocusDeathFromEdit() +{ + KillFocusFroms (IDC_DEATH_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusDeathToEdit() +{ + KillFocusTos (IDC_DEATH_TO_EDIT); +} + +void CAnimStatesDialog::OnKillfocusFlinchFromEdit() +{ + KillFocusFroms (IDC_FLINCH_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusFlinchToEdit() +{ + KillFocusTos (IDC_FLINCH_TO_EDIT); +} + +void CAnimStatesDialog::OnKillfocusFlyingFromEdit() +{ + KillFocusFroms (IDC_FLYING_FROM_EDIT); +} + +void CAnimStatesDialog::OnKillfocusFlyingToEdit() +{ + KillFocusTos (IDC_FLYING_TO_EDIT); +} + +void CAnimStatesDialog::OnKillfocusIdleFromEdit() +{ + KillFocusFroms (IDC_IDLE_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusIdleToEdit() +{ + KillFocusTos (IDC_IDLE_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusJumpingFromEdit() +{ + KillFocusFroms (IDC_JUMPING_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusJumpingToEdit() +{ + + KillFocusTos (IDC_JUMPING_TO_EDIT); +} + +void CAnimStatesDialog::OnKillfocusMelee1FromEdit() +{ + KillFocusFroms (IDC_MELEE1_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusMelee1ToEdit() +{ + KillFocusTos (IDC_MELEE1_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusMelee2FromEdit() +{ + KillFocusFroms (IDC_MELEE2_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusMissile1FromEdit() +{ + + KillFocusFroms (IDC_MISSILE1_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusMissile1ToEdit() +{ + KillFocusTos (IDC_MISSILE1_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusMissile2FromEdit() +{ + KillFocusFroms (IDC_MISSILE2_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusMissile2ToEdit() +{ + KillFocusTos (IDC_MISSILE2_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusMrecoil1ToEdit() +{ + KillFocusTos (IDC_MRECOIL1_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusMrecoil1FromEdit() +{ + KillFocusFroms (IDC_MRECOIL1_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusMrecoil2FromEdit() +{ + KillFocusFroms (IDC_MRECOIL2_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusMrecoil2ToEdit() +{ + KillFocusTos (IDC_MRECOIL2_TO_EDIT); +} + +void CAnimStatesDialog::OnKillfocusQuirkFromEdit() +{ + KillFocusFroms (IDC_QUIRK_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusQuirkToEdit() +{ + KillFocusTos (IDC_QUIRK_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusRecoil1FromEdit() +{ + KillFocusFroms (IDC_RECOIL1_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusRecoil1ToEdit() +{ + KillFocusTos (IDC_RECOIL1_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusRecoil2FromEdit() +{ + KillFocusFroms (IDC_RECOIL2_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusRecoil2ToEdit() +{ + KillFocusTos (IDC_RECOIL2_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusRollingFromEdit() +{ + KillFocusFroms (IDC_ROLLING_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusRollingToEdit() +{ + KillFocusTos (IDC_ROLLING_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusSpecial1FromEdit() +{ + KillFocusFroms (IDC_SPECIAL1_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusSpecial1ToEdit() +{ + KillFocusTos (IDC_SPECIAL1_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusSpecial2FromEdit() +{ + KillFocusFroms (IDC_SPECIAL2_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusSpecial2ToEdit() +{ + KillFocusTos (IDC_SPECIAL2_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusSpecial3FromEdit() +{ + KillFocusFroms (IDC_SPECIAL3_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusSpecial3ToEdit() +{ + KillFocusTos (IDC_SPECIAL3_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusSpecial4FromEdit() +{ + + KillFocusFroms (IDC_SPECIAL4_FROM_EDIT); +} + +void CAnimStatesDialog::OnKillfocusSpecial4ToEdit() +{ + KillFocusTos (IDC_SPECIAL4_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusSpecial5FromEdit() +{ + KillFocusFroms (IDC_SPECIAL5_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusSpecial5ToEdit() +{ + KillFocusTos (IDC_SPECIAL5_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusStandingFromEdit() +{ + KillFocusFroms (IDC_STANDING_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusStandingToEdit() +{ + KillFocusTos (IDC_STANDING_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusTauntFromEdit() +{ + KillFocusFroms (IDC_TAUNT_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusTauntToEdit() +{ + KillFocusTos (IDC_TAUNT_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusWalkingFromEdit() +{ + KillFocusFroms (IDC_WALKING_FROM_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusWalkingToEdit() +{ + KillFocusTos (IDC_WALKING_TO_EDIT); + +} + +void CAnimStatesDialog::OnKillfocusMelee2ToEdit() +{ + KillFocusTos (IDC_MELEE2_TO_EDIT); + +} + +void CAnimStatesDialog::OnResetAnimZero() +{ + int mc=m_current_state; + + memset (m_anim[mc].elem,0,NUM_ANIMS_PER_CLASS*sizeof(anim_entry)); + UpdateDialog(); +} + +void CAnimStatesDialog::OnRotLeft() +{ + m_SpinFrame-=3; +} + +void CAnimStatesDialog::OnRotRight() +{ + m_SpinFrame+=3; +} + +//Copy data from CAnimStatesDialog class to anim struct +void CAnimStatesDialog::GetAnimData(anim_elem *anim_info) +{ + for (int i=0;icaps; + if(d->caps&TCBD_XY){ + desc.x = d->x; + desc.y = d->y; + } + if(d->caps&TCBD_LOOPING){ + desc.looping = d->looping; + } + if(d->caps&TCBD_WAITTIME){ + desc.waittime = d->waittime; + } + if(d->caps&TCBD_SPEED){ + desc.speed = d->speed; + } + if(d->flags&TC_NOEARLYRENDER) + { + m_NoRenderUntilStart = true; + } + + desc.type = d->type; + desc.flags = d->flags; + strcpy(desc.filename,d->filename); + desc.mission_mask_set = d->mission_mask_set; + desc.mission_mask_unset = d->mission_mask_unset; + } + + switch(desc.type){ + case TC_BMP_STATIC: + m_iEffectType = 0; + break; + case TC_BMP_BLUR: + if(desc.flags==TC_BMPF_IN) + m_iEffectType = 1; + else + m_iEffectType = 2; + break; + case TC_BMP_SCANLINE: + if(desc.flags==TC_BMPF_IN) + m_iEffectType = 3; + else + m_iEffectType = 4; + break; + case TC_BMP_INVERT: + if(desc.flags==TC_BMPF_IN) + m_iEffectType = 5; + else + m_iEffectType = 6; + break; + case TC_BMP_STRETCH: + if(desc.flags==TC_BMPF_IN) + m_iEffectType = 7; + else + m_iEffectType = 8; + break; + } + + m_sFilename = desc.filename; + m_fSpeed = desc.speed; + m_fStartTime = desc.waittime; + m_iX = desc.x; + m_iY = desc.y; +} + + +void CBriefBitmapEdit::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBriefBitmapEdit) + DDX_Text(pDX, IDC_BRIEF_B_FILENAME, m_sFilename); + DDX_Text(pDX, IDC_BRIEF_B_SPEED, m_fSpeed); + DDV_MinMaxFloat(pDX, m_fSpeed, 0.f, 99999.f); + DDX_Text(pDX, IDC_BRIEF_B_STARTTIME, m_fStartTime); + DDV_MinMaxFloat(pDX, m_fStartTime, 0.f, 99999.f); + DDX_Text(pDX, IDC_BRIEF_B_X, m_iX); + DDV_MinMaxInt(pDX, m_iX, 0, 639); + DDX_Text(pDX, IDC_BRIEF_B_Y, m_iY); + DDV_MinMaxInt(pDX, m_iY, 0, 479); + DDX_Radio(pDX, IDC_BRIEF_B_STATIC, m_iEffectType); + DDX_Text(pDX, IDC_BRIEF_B_DESC, m_sDesc); + DDX_Check(pDX, IDC_BRIEF_B_NORENDER, m_NoRenderUntilStart); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CBriefBitmapEdit, CDialog) + //{{AFX_MSG_MAP(CBriefBitmapEdit) + ON_BN_CLICKED(IDC_BRIEF_B_CHOOSE, OnBriefBChoose) + ON_CBN_SELCHANGE(IDC_BRIEF_B_PREDEF, OnSelchangeBriefBPredef) + ON_BN_CLICKED(IDC_MISSIONFLAGS, OnMissionflags) + ON_BN_CLICKED(IDC_BRIEF_B_NORENDER, OnBriefBNorender) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBriefBitmapEdit message handlers + +void CBriefBitmapEdit::OnOK() +{ + UpdateData(true); + + if(!cfexist(m_sFilename.GetBuffer(0))){ + MessageBox("Not A Valid Filename","Error"); + return; + } + + desc.caps = TCBD_XY|TCBD_LOOPING|TCBD_WAITTIME|TCBD_SPEED; + strcpy(desc.filename,m_sFilename); + desc.speed = m_fSpeed; + desc.waittime = m_fStartTime; + desc.x = m_iX; + desc.y = m_iY; + + switch(m_iEffectType){ + case 0: desc.type = TC_BMP_STATIC; desc.flags = TC_BMPF_IN; break; + case 1: desc.type = TC_BMP_BLUR; desc.flags = TC_BMPF_IN; break; + case 2: desc.type = TC_BMP_BLUR; desc.flags = TC_BMPF_OUT; break; + case 3: desc.type = TC_BMP_SCANLINE; desc.flags = TC_BMPF_IN; break; + case 4: desc.type = TC_BMP_SCANLINE; desc.flags = TC_BMPF_OUT; break; + case 5: desc.type = TC_BMP_INVERT; desc.flags = TC_BMPF_IN; break; + case 6: desc.type = TC_BMP_INVERT; desc.flags = TC_BMPF_OUT; break; + case 7: desc.type = TC_BMP_STRETCH; desc.flags = TC_BMPF_IN; break; + case 8: desc.type = TC_BMP_STRETCH; desc.flags = TC_BMPF_OUT; break; + } + + if(m_NoRenderUntilStart) + desc.flags |= TC_NOEARLYRENDER; + else + desc.flags &= ~TC_NOEARLYRENDER; + + CDialog::OnOK(); +} + +void CBriefBitmapEdit::OnBriefBChoose() +{ + UpdateData(true); + char szFilter[] = "Outrage Graphic Files (*.ogf)|*.ogf|32bit Uncompressed Targa (*.tga)|*.tga|PCX (*.pcx)|*.pcx|All Files (*.*)|*.*||"; + CFileDialog dlg(true,NULL,NULL,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,szFilter); + + if(dlg.DoModal()==IDOK){ + //handle + m_sFilename = dlg.GetFileName(); + UpdateData(false); + } +} + +BOOL CBriefBitmapEdit::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_B_PREDEF); + combo->AddString(""); + combo->SetCurSel(0); + + int layout = -1; + + for(int i=0;i<(*PBnum_layouts);i++){ + if(!stricmp(Briefing_screens[m_Screen].layout,PBlayouts[i].filename)) + layout = i; + } + + if(layout!=-1){ + int count = PBlayouts[layout].num_bmps; + for(int j=0;jAddString(buffer); + } + } + + UpdateData(false); + + return TRUE; +} + +void CBriefBitmapEdit::OnSelchangeBriefBPredef() +{ + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_B_PREDEF); + int item = combo->GetCurSel(); + + if(item<=0) + return; + + UpdateData(true); + + int layout = -1; + + for(int i=0;i<(*PBnum_layouts);i++){ + if(!stricmp(Briefing_screens[m_Screen].layout,PBlayouts[i].filename)) + layout = i; + } + + if(layout!=-1){ + m_iX = PBlayouts[layout].bmps[item-1].x; + m_iY = PBlayouts[layout].bmps[item-1].y; + UpdateData(false); + } + +} + +void CBriefBitmapEdit::OnMissionflags() +{ + CBriefMissionFlagsDlg dlg(desc.mission_mask_set,desc.mission_mask_unset); + + if(dlg.DoModal()){ + desc.mission_mask_set = dlg.m_Set; + desc.mission_mask_unset = dlg.m_UnSet; + } +} + +void CBriefBitmapEdit::OnBriefBNorender() +{ +} diff --git a/editor/BriefBitmapEdit.h b/editor/BriefBitmapEdit.h new file mode 100644 index 00000000..fecca5ab --- /dev/null +++ b/editor/BriefBitmapEdit.h @@ -0,0 +1,63 @@ +#if !defined(AFX_BRIEFBITMAPEDIT_H__01F120A1_427B_11D2_B359_006008BF0B09__INCLUDED_) +#define AFX_BRIEFBITMAPEDIT_H__01F120A1_427B_11D2_B359_006008BF0B09__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// BriefBitmapEdit.h : header file +// + +#include "telcomefxstructs.h" +#include "TelcomEffects.h" + +///////////////////////////////////////////////////////////////////////////// +// CBriefBitmapEdit dialog + +class CBriefBitmapEdit : public CDialog +{ +// Construction +public: + CBriefBitmapEdit(int curr_screen = 0,LPTCBMPDESC d=NULL,CWnd* pParent = NULL); // standard constructor + TCBMPDESC desc; + int m_Screen; + +// Dialog Data + //{{AFX_DATA(CBriefBitmapEdit) + enum { IDD = IDD_BRIEF_ADDBITMAP }; + CString m_sFilename; + float m_fSpeed; + float m_fStartTime; + int m_iX; + int m_iY; + int m_iEffectType; + CString m_sDesc; + BOOL m_NoRenderUntilStart; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBriefBitmapEdit) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CBriefBitmapEdit) + virtual void OnOK(); + afx_msg void OnBriefBChoose(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeBriefBPredef(); + afx_msg void OnMissionflags(); + afx_msg void OnBriefBNorender(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BRIEFBITMAPEDIT_H__01F120A1_427B_11D2_B359_006008BF0B09__INCLUDED_) diff --git a/editor/BriefButtonEdit.cpp b/editor/BriefButtonEdit.cpp new file mode 100644 index 00000000..3bdbdafd --- /dev/null +++ b/editor/BriefButtonEdit.cpp @@ -0,0 +1,473 @@ +// BriefButtonEdit.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "BriefButtonEdit.h" +#include "CFile.h" +#include "BriefMissionFlagsDlg.h" +#include "briefedit.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBriefButtonEdit dialog + + +CBriefButtonEdit::CBriefButtonEdit(LPTCBUTTONDESC d,int id,CWnd* pParent /*=NULL*/) + : CDialog(CBriefButtonEdit::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBriefButtonEdit) + m_sFilename = _T(""); + m_sFlashFilename = _T(""); + m_bFlasher = FALSE; + m_fFlashStart = 0.0f; + m_bGlow = FALSE; + m_iID = 0; + m_iPID = 0; + m_iSID = 0; + m_iClickType = -1; + m_iButtonType = -1; + m_sDesc = _T(""); + m_sFilenameFocus = _T(""); + m_sFlashFilenameFocus = _T(""); + m_iX = 0; + m_iY = 0; + m_ScreenToJump = 0; + //}}AFX_DATA_INIT + + m_iID = id; + + memset(&desc,0,sizeof(TCBUTTONDESC)); + + desc.mission_mask_set = 0; + desc.mission_mask_unset = 0; + + if(d){ + //initialize to what was passed in + strcpy(desc.filename,d->filename); + strcpy(desc.filename_focus,d->filename_focus); + if(d->flasher){ + desc.flasher = true; + desc.flash_time = d->flash_time; + strcpy(desc.flash_filename,d->flash_filename); + strcpy(desc.flash_filename_focus,d->flash_filename_focus); + } + desc.sibling_id = d->sibling_id; + desc.parent_id = d->parent_id; + desc.x = d->x; desc.y = d->y; + desc.w = d->w; desc.h = d->h; + desc.osflags = d->osflags; + desc.button_type = d->button_type; + desc.click_type = d->click_type; + desc.mission_mask_set = d->mission_mask_set; + desc.mission_mask_unset = d->mission_mask_unset; + desc.jump_page = d->jump_page; + + }else{ + //set all defaults + desc.button_type = BUTT_NEXTPAGE; + desc.click_type = CLICKTYPE_CLICKDOWN; + } + + m_ScreenToJump = 0; + switch(desc.button_type){ + case BUTT_UPARROW: + m_iButtonType = 0; + break; + case BUTT_DOWNARROW: + m_iButtonType = 1; + break; + case BUTT_NEXTPAGE: + m_iButtonType = 2; + break; + case BUTT_PREVPAGE: + m_iButtonType = 3; + break; + case BUTT_QUIT: + m_iButtonType = 4; + break; + case BUTT_JUMP: + m_iButtonType = 5; + m_ScreenToJump = desc.jump_page; + break; + default: + m_iButtonType = 0; + break; + } + + switch(desc.click_type){ + case CLICKTYPE_CLICKUP: + m_iClickType = 0; + break; + case CLICKTYPE_CLICKDOWN: + m_iClickType = 1; + break; + case CLICKTYPE_DOWN: + m_iClickType = 2; + break; + default: + m_iClickType = 0; + break; + } + + m_sFilename = desc.filename; + m_sFilenameFocus = desc.filename_focus; + if(desc.flasher){ + m_sFlashFilename = desc.flash_filename; + m_sFlashFilenameFocus = desc.flash_filename_focus; + } + if(desc.osflags&OBF_GLOW) + m_bGlow = true; + else + m_bGlow = false; + if(desc.osflags&OBF_FLASH){ + m_bFlasher = true; + m_fFlashStart = desc.flash_time; + }else{ + m_bFlasher = false; + m_fFlashStart = 0; + } + + m_iPID = desc.parent_id; + m_iSID = desc.sibling_id; + m_iX = desc.x; + m_iY = desc.y; +} + + +void CBriefButtonEdit::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBriefButtonEdit) + DDX_Text(pDX, IDC_BRIEF_BT_FILENAME, m_sFilename); + DDX_Text(pDX, IDC_BRIEF_BT_FLASH_FILENAME, m_sFlashFilename); + DDX_Check(pDX, IDC_BRIEF_BT_FLASHER, m_bFlasher); + DDX_Text(pDX, IDC_BRIEF_BT_FLASHSTART, m_fFlashStart); + DDV_MinMaxFloat(pDX, m_fFlashStart, 0.f, 99999.f); + DDX_Check(pDX, IDC_BRIEF_BT_GLOW, m_bGlow); + DDX_Text(pDX, IDC_BRIEF_BT_ID, m_iID); + DDX_Text(pDX, IDC_BRIEF_BT_PID, m_iPID); + DDX_Text(pDX, IDC_BRIEF_BT_SID, m_iSID); + DDX_Radio(pDX, IDC_BRIEF_BT_MOUSEUP, m_iClickType); + DDX_Radio(pDX, IDC_BRIEF_BT_SCROLLUP, m_iButtonType); + DDX_Text(pDX, IDC_BRIEF_BT_DESC, m_sDesc); + DDX_Text(pDX, IDC_BRIEF_BT_FILENAME_FOCUS, m_sFilenameFocus); + DDX_Text(pDX, IDC_BRIEF_BT_FLASH_FILENAME_FOCUS, m_sFlashFilenameFocus); + DDX_Text(pDX, IDC_BRIEF_BT_X, m_iX); + DDX_Text(pDX, IDC_BRIEF_BT_Y, m_iY); + DDX_Text(pDX, IDC_BRIEF_BT_JUMP_SCREEN, m_ScreenToJump); + DDV_MinMaxInt(pDX, m_ScreenToJump, 0, 64); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CBriefButtonEdit, CDialog) + //{{AFX_MSG_MAP(CBriefButtonEdit) + ON_BN_CLICKED(IDC_BRIEF_BT_CHOOSE, OnBriefBtChoose) + ON_BN_CLICKED(IDC_BRIEF_BT_FLASH_CHOOSE, OnBriefBtFlashChoose) + ON_BN_CLICKED(IDC_BRIEF_BT_FLASHER, OnBriefBtFlasher) + ON_BN_CLICKED(IDC_BRIEF_BT_GLOW, OnBriefBtGlow) + ON_BN_CLICKED(IDC_BRIEF_BT_CHOOSE_FOCUS, OnBriefBtChooseFocus) + ON_BN_CLICKED(IDC_BRIEF_BT_FLASH_CHOOSE_FOCUS, OnBriefBtFlashChooseFocus) + ON_BN_CLICKED(IDC_MISSIONFLAGS, OnMissionflags) + ON_BN_CLICKED(IDC_BRIEF_BT_JUMP, OnBriefBtJump) + ON_BN_CLICKED(IDC_BRIEF_BT_NEXTSCREEN, OnBriefBtNextscreen) + ON_BN_CLICKED(IDC_BRIEF_BT_PREVSCREEN, OnBriefBtPrevscreen) + ON_BN_CLICKED(IDC_BRIEF_BT_QUIT, OnBriefBtQuit) + ON_BN_CLICKED(IDC_BRIEF_BT_SCROLLDOWN, OnBriefBtScrolldown) + ON_BN_CLICKED(IDC_BRIEF_BT_SCROLLUP, OnBriefBtScrollup) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBriefButtonEdit message handlers + +void CBriefButtonEdit::OnBriefBtChoose() +{ + UpdateData(true); + char szFilter[] = "Outrage Graphic Files (*.ogf)|*.ogf|32bit Uncompressed Targa (*.tga)|*.tga|PCX (*.pcx)|*.pcx|All Files (*.*)|*.*||"; + CFileDialog dlg(true,NULL,NULL,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,szFilter); + + if(dlg.DoModal()==IDOK){ + //handle + m_sFilename = dlg.GetFileName(); + UpdateData(false); + } +} + +void CBriefButtonEdit::OnBriefBtFlashChoose() +{ + UpdateData(true); + char szFilter[] = "Outrage Graphic Files (*.ogf)|*.ogf|32bit Uncompressed Targa (*.tga)|*.tga|PCX (*.pcx)|*.pcx|All Files (*.*)|*.*||"; + CFileDialog dlg(true,NULL,NULL,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,szFilter); + + if(dlg.DoModal()==IDOK){ + //handle + m_sFlashFilename = dlg.GetFileName(); + UpdateData(false); + } +} + +void CBriefButtonEdit::OnOK() +{ + if(!VerifyData()) + return; + + desc.osflags = 0; + if(m_bFlasher || m_bGlow){ + desc.flasher = true; + if(m_bFlasher) + desc.osflags |= OBF_FLASH; + if(m_bGlow) + desc.osflags |= OBF_GLOW; + + }else{ + desc.flasher = false; + } + + //If we got here then fill in all the data + if(desc.flasher){ + //we need to get flash information + strcpy(desc.flash_filename,m_sFlashFilename.GetBuffer(0)); + strcpy(desc.flash_filename_focus,m_sFlashFilenameFocus.GetBuffer(0)); + if(desc.osflags&OBF_FLASH){ + //get flash start time + desc.flash_time = m_fFlashStart; + } + }else{ + desc.flash_filename[0] = '\0'; + desc.flash_filename_focus[0] = '\0'; + } + + desc.parent_id = m_iPID; + desc.sibling_id = m_iSID; + desc.x = m_iX; + desc.y = m_iY; + desc.jump_page = m_ScreenToJump; + + switch(m_iButtonType){ + case 0: desc.button_type = BUTT_UPARROW; break; + case 1: desc.button_type = BUTT_DOWNARROW; break; + case 2: desc.button_type = BUTT_NEXTPAGE; break; + case 3: desc.button_type = BUTT_PREVPAGE; break; + case 4: desc.button_type = BUTT_QUIT; break; + case 5: desc.button_type = BUTT_JUMP; break; + } + + switch(m_iClickType){ + case 0: desc.click_type = CLICKTYPE_CLICKUP; break; + case 1: desc.click_type = CLICKTYPE_CLICKDOWN; break; + case 2: desc.click_type = CLICKTYPE_DOWN; break; + } + + strcpy(desc.filename,m_sFilename.GetBuffer(0)); + strcpy(desc.filename_focus,m_sFilenameFocus.GetBuffer(0)); + + CDialog::OnOK(); +} + +BOOL CBriefButtonEdit::OnInitDialog() +{ + CDialog::OnInitDialog(); + + UpdateData(false); + + UpdateDialog(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CBriefButtonEdit::UpdateDialog(void) +{ + CEdit *edit; + CButton *but; + edit = (CEdit *)GetDlgItem(IDC_BRIEF_BT_FLASH_FILENAME); + but = (CButton *)GetDlgItem(IDC_BRIEF_BT_FLASH_CHOOSE); + + if( (desc.osflags&OBF_FLASH) || (desc.osflags&OBF_GLOW) ){ + //Enable the flash filename window + edit->EnableWindow(true); + but->EnableWindow(true); + + edit = (CEdit *)GetDlgItem(IDC_BRIEF_BT_FLASHSTART); + if(desc.osflags&OBF_FLASH) + edit->EnableWindow(true); + else + edit->EnableWindow(false); + + edit = (CEdit *)GetDlgItem(IDC_BRIEF_BT_FLASH_FILENAME_FOCUS); + edit->EnableWindow(true); + }else{ + edit->EnableWindow(false); + but->EnableWindow(false); + edit = (CEdit *)GetDlgItem(IDC_BRIEF_BT_FLASHSTART); + edit->EnableWindow(false); + edit = (CEdit *)GetDlgItem(IDC_BRIEF_BT_FLASH_FILENAME_FOCUS); + edit->EnableWindow(false); + } + + OnBriefBtJump(); +} + +void CBriefButtonEdit::OnBriefBtFlasher() +{ + UpdateData(true); + if(m_bFlasher) + desc.osflags |= OBF_FLASH; + else + desc.osflags &= ~OBF_FLASH; + if(m_bFlasher||m_bGlow) + desc.flasher = true; + else + desc.flasher = false; + UpdateDialog(); +} + +void CBriefButtonEdit::OnBriefBtGlow() +{ + UpdateData(true); + if(m_bGlow) + desc.osflags |= OBF_GLOW; + else + desc.osflags &= ~OBF_GLOW; + if(m_bFlasher||m_bGlow) + desc.flasher = true; + else + desc.flasher = false; + UpdateDialog(); +} + +extern int Briefing_root_screen; +extern tBriefScreen Briefing_screens[MAX_TELCOM_SCREENS]; + +bool CBriefButtonEdit::VerifyData(void) +{ + UpdateData(true); + bool ret = true; + + if(desc.flasher){ + //flash filename should be specified + if(!cfexist(m_sFlashFilename.GetBuffer(0))){ + //file doesn't exist + MessageBox("Flash Filename Does Not Exist","Error"); + ret = false; + } + //flash focus filename should be specified + if(!cfexist(m_sFlashFilenameFocus.GetBuffer(0))){ + //file doesn't exist + MessageBox("Flash Focus Filename Does Not Exist","Error"); + ret = false; + } + } + + //filename should be specified + if(!cfexist(m_sFilename.GetBuffer(0))){ + //file doesn't exist + MessageBox("Filename Does Not Exist","Error"); + ret = false; + } + + //focus filename should be specified + if(!cfexist(m_sFilenameFocus.GetBuffer(0))){ + //file doesn't exist + MessageBox("Focus Filename Does Not Exist","Error"); + ret = false; + } + + if(desc.button_type==BUTT_JUMP) + { + //verify the jump screen exists + int num_screens = 0; + int curr = Briefing_root_screen; + while(curr!=-1) + { + num_screens++; + curr = Briefing_screens[curr].next; + } + + if(m_ScreenToJump<0 || m_ScreenToJump>=num_screens) + { + //invalid screen + MessageBox("The Jump-To Screen Does Not Exist","Error"); + ret = false; + } + } + + return ret; +} +void CBriefButtonEdit::OnBriefBtChooseFocus() +{ + UpdateData(true); + char szFilter[] = "Outrage Graphic Files (*.ogf)|*.ogf|32bit Uncompressed Targa (*.tga)|*.tga|PCX (*.pcx)|*.pcx|All Files (*.*)|*.*||"; + CFileDialog dlg(true,NULL,NULL,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,szFilter); + + if(dlg.DoModal()==IDOK){ + //handle + m_sFilenameFocus = dlg.GetFileName(); + UpdateData(false); + } +} + +void CBriefButtonEdit::OnBriefBtFlashChooseFocus() +{ + UpdateData(true); + char szFilter[] = "Outrage Graphic Files (*.ogf)|*.ogf|32bit Uncompressed Targa (*.tga)|*.tga|PCX (*.pcx)|*.pcx|All Files (*.*)|*.*||"; + CFileDialog dlg(true,NULL,NULL,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,szFilter); + + if(dlg.DoModal()==IDOK){ + //handle + m_sFlashFilenameFocus = dlg.GetFileName(); + UpdateData(false); + } +} + +void CBriefButtonEdit::OnMissionflags() +{ + CBriefMissionFlagsDlg dlg(desc.mission_mask_set,desc.mission_mask_unset); + + if(dlg.DoModal()){ + desc.mission_mask_set = dlg.m_Set; + desc.mission_mask_unset = dlg.m_UnSet; + } +} + +void CBriefButtonEdit::OnBriefBtJump() +{ + CButton *button = (CButton *)GetDlgItem(IDC_BRIEF_BT_JUMP); + CEdit *edit = (CEdit *)GetDlgItem(IDC_BRIEF_BT_JUMP_SCREEN); + + if((button->GetState()&0x03)!=0) + edit->EnableWindow(true); + else + edit->EnableWindow(false); +} + +void CBriefButtonEdit::OnBriefBtNextscreen() +{ + OnBriefBtJump(); +} + +void CBriefButtonEdit::OnBriefBtPrevscreen() +{ + OnBriefBtJump(); +} + +void CBriefButtonEdit::OnBriefBtQuit() +{ + OnBriefBtJump();} + +void CBriefButtonEdit::OnBriefBtScrolldown() +{ + OnBriefBtJump(); +} + +void CBriefButtonEdit::OnBriefBtScrollup() +{ + OnBriefBtJump(); +} diff --git a/editor/BriefButtonEdit.h b/editor/BriefButtonEdit.h new file mode 100644 index 00000000..e96e14da --- /dev/null +++ b/editor/BriefButtonEdit.h @@ -0,0 +1,81 @@ +#if !defined(AFX_BRIEFBUTTONEDIT_H__01F120A2_427B_11D2_B359_006008BF0B09__INCLUDED_) +#define AFX_BRIEFBUTTONEDIT_H__01F120A2_427B_11D2_B359_006008BF0B09__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// BriefButtonEdit.h : header file +// + +#include "telcomefxstructs.h" +#include "TelcomEffects.h" + +///////////////////////////////////////////////////////////////////////////// +// CBriefButtonEdit dialog + +class CBriefButtonEdit : public CDialog +{ +// Construction +public: + TCBUTTONDESC desc; + CBriefButtonEdit(LPTCBUTTONDESC desc=NULL,int id=0,CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CBriefButtonEdit) + enum { IDD = IDD_BRIEF_ADDBUTTON }; + CString m_sFilename; + CString m_sFlashFilename; + BOOL m_bFlasher; + float m_fFlashStart; + BOOL m_bGlow; + int m_iID; + int m_iPID; + int m_iSID; + int m_iClickType; + int m_iButtonType; + CString m_sDesc; + CString m_sFilenameFocus; + CString m_sFlashFilenameFocus; + int m_iX; + int m_iY; + int m_ScreenToJump; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBriefButtonEdit) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + void UpdateDialog(void); + bool VerifyData(void); + + // Generated message map functions + //{{AFX_MSG(CBriefButtonEdit) + afx_msg void OnBriefBtChoose(); + afx_msg void OnBriefBtFlashChoose(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnBriefBtFlasher(); + afx_msg void OnBriefBtGlow(); + afx_msg void OnBriefBtChooseFocus(); + afx_msg void OnBriefBtFlashChooseFocus(); + afx_msg void OnMissionflags(); + afx_msg void OnBriefBtJump(); + afx_msg void OnBriefBtNextscreen(); + afx_msg void OnBriefBtPrevscreen(); + afx_msg void OnBriefBtQuit(); + afx_msg void OnBriefBtScrolldown(); + afx_msg void OnBriefBtScrollup(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BRIEFBUTTONEDIT_H__01F120A2_427B_11D2_B359_006008BF0B09__INCLUDED_) diff --git a/editor/BriefEdit.cpp b/editor/BriefEdit.cpp new file mode 100644 index 00000000..0a9024c9 --- /dev/null +++ b/editor/BriefEdit.cpp @@ -0,0 +1,2223 @@ +// BriefEdit.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "BriefEdit.h" +#include "mono.h" +#include "BriefingParse.h" + +#include "BriefBitmapEdit.h" +#include "BriefButtonEdit.h" +#include "BriefMovieEdit.h" +#include "BriefScreenEdit.h" +#include "BriefSoundEdit.h" +#include "BriefTextEdit.h" +#include "Telcom.h" +#include "BriefManage.h" +#include "mem.h" +#include "textaux.h" +#include "ddio.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBriefEdit dialog + +tLayoutScreen *PBlayouts; +int *PBnum_layouts; +int TCx,TCy; + +CBriefEdit::CBriefEdit(CWnd* pParent /*=NULL*/) + : CDialog(CBriefEdit::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBriefEdit) + m_fGlitch = 0.0f; + m_fStatic = 0.0f; + m_sTitle = _T(""); + //}}AFX_DATA_INIT + layouts = NULL; + num_layouts = 0; + ParseLayoutScreenFile("BriefingLayouts.txt"); + PBlayouts = layouts; + PBnum_layouts = &num_layouts; + layout_bmp = -1; + TCx = TCy = 0; + + + int bm_handle = bm_AllocLoadFileBitmap("TelCom.ogf", 0); + if (bm_handle >BAD_BITMAP_HANDLE){ + + menutga_LoadHotSpotMap(bm_handle,HOTSPOT_DISPLAY,&hotspotmap,&windowmap); + + TCx = windowmap.wm[MONITOR_MAIN].x; + TCy = windowmap.wm[MONITOR_MAIN].y; + + FreeHotSpotMapInternals(&hotspotmap); + FreeViewports(); + if(windowmap.wm) mem_free(windowmap.wm); + bm_FreeBitmap(bm_handle); + } +} + + +void CBriefEdit::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBriefEdit) + DDX_Text(pDX, IDC_BRIEF_GLITCH, m_fGlitch); + DDV_MinMaxFloat(pDX, m_fGlitch, 0.f, 1.f); + DDX_Text(pDX, IDC_BRIEF_STATIC, m_fStatic); + DDV_MinMaxFloat(pDX, m_fStatic, 0.f, 1.f); + DDX_Text(pDX, IDC_BRIEF_TITLE, m_sTitle); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CBriefEdit, CDialog) + //{{AFX_MSG_MAP(CBriefEdit) + ON_BN_CLICKED(IDC_BRIEF_EFFECT_BITMAP, OnBriefEffectBitmap) + ON_BN_CLICKED(IDC_BRIEF_EFFECT_BUTTON, OnBriefEffectButton) + ON_BN_CLICKED(IDC_BRIEF_EFFECT_DEL, OnBriefEffectDel) + ON_BN_CLICKED(IDC_BRIEF_EFFECT_EDIT, OnBriefEffectEdit) + ON_BN_CLICKED(IDC_BRIEF_EFFECT_MOVIE, OnBriefEffectMovie) + ON_BN_CLICKED(IDC_BRIEF_EFFECT_SOUND, OnBriefEffectSound) + ON_BN_CLICKED(IDC_BRIEF_EFFECT_TEXT, OnBriefEffectText) + ON_BN_CLICKED(IDC_BRIEF_SCREEN_ADD, OnBriefScreenAdd) + ON_BN_CLICKED(IDC_BRIEF_SCREEN_DEL, OnBriefScreenDel) + ON_BN_CLICKED(IDC_BRIEF_SCREEN_EDIT, OnBriefScreenEdit) + ON_WM_DESTROY() + ON_CBN_SELCHANGE(IDC_BRIEF_SCREEN_LIST, OnSelchangeBriefScreenList) + ON_BN_CLICKED(IDC_BRIEF_SAVE, OnBriefSave) + ON_BN_CLICKED(IDC_LOAD, OnLoad) + ON_WM_TIMER() + ON_BN_CLICKED(IDC_MANAGE, OnManage) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + + +/* + **************************************************************************** + * Functions to manipulate effects/screens in briefing editor * + **************************************************************************** + * +*/ +bool Briefing_free_called = true; //if this is true it's ok to Init screens +int Briefing_root_screen; +tBriefScreen Briefing_screens[MAX_TELCOM_SCREENS]; + +// BriefEditInitScreens +// +// Initializes the briefing screens so they are empty +void BriefEditInitScreens(void) +{ + ASSERT(Briefing_free_called); + Briefing_free_called = false; + + Briefing_root_screen = -1; + + for(int scr = 0;scrused = false; + bscr->root_effect = -1; + bscr->next = -1; + bscr->prev = -1; + bscr->layout[0] = '\0'; + bscr->mission_mask_set = 0; + bscr->mission_mask_unset = 0; + + for(int eff = 0;effeffects[eff]); + } + } +} + +// BriefEditInitEffect +// +// Initializes an effect to empty +void BriefEditInitEffect(tBriefEffect *efx) +{ + ASSERT(efx); + + memset(efx,0,sizeof(tBriefEffect)); + + efx->type = BE_NONE; + efx->used = false; + efx->id = 0; + efx->text = NULL; + efx->next = -1; + efx->prev = -1; + efx->w = efx->h = -1; + efx->description[0] = '\0'; +} + +// BriefEditFreeScreen +// +// Frees a screen +void BriefEditFreeScreen(tBriefScreen *bscr) +{ + bscr->used = false; + bscr->root_effect = -1; + bscr->prev = bscr->next = -1; + bscr->layout[0] = '\0'; + + for(int eff = 0; eff < MAX_EFFECTS_PER_SCREEN; eff++){ + if(bscr->effects[eff].used){ + BriefEditFreeEffect(&bscr->effects[eff]); + } + } +} + +// BriefEditFreeScreens +// +// Closes down all the briefing screens, freeing memory +void BriefEditFreeScreens(void) +{ + ASSERT(!Briefing_free_called); + Briefing_free_called = true; + + for(int scr = 0; scr < MAX_TELCOM_SCREENS; scr++ ){ + if(Briefing_screens[scr].used){ + tBriefScreen *bscr = &Briefing_screens[scr]; + BriefEditFreeScreen(bscr); + } + } +} + +// BriefEditFreeEffect +// +// Frees up any memory allocated in an effect +void BriefEditFreeEffect(tBriefEffect *efx) +{ + switch(efx->type){ + case BE_TEXT: + case BE_BMP: + case BE_MOVIE: + case BE_BKG: + case BE_POLY: + case BE_SND: + case BE_BUTTON: + break; + default: + Int3(); //Get Jeff + }; + + if(efx->text){ + mem_free(efx->text); + efx->text = NULL; + } + + efx->used = false; + efx->next = efx->prev = -1; + efx->description[0] = '\0'; + efx->id = 0; + efx->type = BE_NONE; +} + +void BuildMissionFlagMask(uint mask,char *string,ubyte isset) +{ + int counter = 0; + int index = 0; + uint bit = 0x01; + char temp[10]; + + for(index=0;index<32;index++){ + if(mask&bit){ + if(isset) + strcat(string,"isset "); + else + strcat(string,"isnset "); + sprintf(temp,"%d ",counter); + strcat(string,temp); + } + counter++; + bit = bit << 1; + } +} + +// BriefEditSaveScreens +// +// Saves out the screens to a briefing file +ubyte BriefEditSaveScreens(char *filename,CComboBox *screen_combo,BriefGlobalValues *glob) +{ + CFILE *file = cfopen(filename,"wt"); + if(!file) + return 0; + + int curr_screen = Briefing_root_screen; + int curr_effect; + char buffer[9*1024]; + char tempbuffer[512]; + int screen_count = 0; + + //Write out global information + sprintf(buffer,"$title \"%s\"",glob->title); + cf_WriteString(file,buffer); + sprintf(buffer,"$glitch %.3f",glob->glitch_val); + cf_WriteString(file,buffer); + sprintf(buffer,"$static %.3f",glob->static_val); + cf_WriteString(file,buffer); + + cf_WriteString(file,"\n"); + + while(curr_screen!=-1){ + ASSERT(curr_screen>=0 && curr_screenGetLBText(screen_count,tempbuffer); + if(Briefing_screens[curr_screen].layout[0]!='\0') + sprintf(buffer,"$screen %d %s %s desc \"%s\" layout \"%s\" start",screen_count,masksetstr,maskunsetstr,tempbuffer,Briefing_screens[curr_screen].layout); + else + sprintf(buffer,"$screen %d %s %s desc \"%s\" start",screen_count,masksetstr,maskunsetstr,tempbuffer); + cf_WriteString(file,buffer); + + while(curr_effect!=-1){ + ASSERT( curr_effect>=0 && curr_effecttype){ + case TC_TEXT_STATIC: + strcpy(tempbuffer,"None"); + break; + case TC_TEXT_SCROLL: + switch(desc->flags){ + case TC_TEXTF_L2R: + strcpy(tempbuffer,"scroll_l2r"); + break; + case TC_TEXTF_R2L: + strcpy(tempbuffer,"scroll_r2l"); + break; + case TC_TEXTF_T2B: + strcpy(tempbuffer,"scroll_t2b"); + break; + case TC_TEXTF_B2T: + strcpy(tempbuffer,"scroll_b2t"); + break; + default: + strcpy(tempbuffer,"None"); + break; + } + break; + case TC_TEXT_FADE: + switch(desc->flags){ + case TC_TEXTF_IN: + strcpy(tempbuffer,"fade_in"); + break; + case TC_TEXTF_OUT: + strcpy(tempbuffer,"fade_out"); + break; + default: + strcpy(tempbuffer,"fade_in"); + break; + } + break; + case TC_TEXT_FLASH: + strcpy(tempbuffer,"flash"); + break; + default: + strcpy(tempbuffer,"None"); + } + + ubyte red,green,blue; + red = GR_COLOR_RED(desc->color); + green = GR_COLOR_GREEN(desc->color); + blue = GR_COLOR_BLUE(desc->color); + + char font_str[20]; + switch(desc->font){ + case BBRIEF_FONT_INDEX: + strcpy(font_str,"lg_brief"); + break; + default: + strcpy(font_str,"sm_brief"); + break; + } + + char masksetstr[256],maskunsetstr[256]; + masksetstr[0] = '\0'; maskunsetstr[0] = '\0'; + if(desc->mission_mask_set){ + BuildMissionFlagMask(desc->mission_mask_set,masksetstr,1); + } + if(desc->mission_mask_unset){ + BuildMissionFlagMask(desc->mission_mask_unset,maskunsetstr,0); + } + + sprintf(buffer,"$text effect %s font %s %s speed %0.3f box %d,%d,%d,%d color %d,%d,%d desc \"%s\" id %d starttime %0.3f %s %s show",tempbuffer, + font_str,(desc->caps&TCTD_TABSTOP)?"tabstop":"",desc->speed,desc->textbox.left,desc->textbox.right,desc->textbox.top,desc->textbox.bottom, + red,green,blue,effects[curr_effect].description,effects[curr_effect].id,desc->waittime,masksetstr,maskunsetstr); + cf_WriteString(file,buffer); + + //now write out all the text + char *p = effects[curr_effect].text; + while(p){ + p = textaux_CopyTextLine(p,buffer); + cf_WriteString(file,buffer); + } + + cf_WriteString(file,"$endtext"); + }break; + case BE_BMP: + { + LPTCBMPDESC desc = &effects[curr_effect].bmp_desc; + switch(desc->type){ + case TC_BMP_STATIC: + strcpy(tempbuffer,"None"); + break; + case TC_BMP_BLUR: + if(desc->flags==TC_BMPF_IN) + strcpy(tempbuffer,"Blur_in"); + else + strcpy(tempbuffer,"Blur_out"); + break; + case TC_BMP_SCANLINE: + if(desc->flags==TC_BMPF_IN) + strcpy(tempbuffer,"Scan_in"); + else + strcpy(tempbuffer,"Scan_out"); + break; + case TC_BMP_INVERT: + if(desc->flags==TC_BMPF_IN) + strcpy(tempbuffer,"Invert_in"); + else + strcpy(tempbuffer,"Invert_out"); + break; + case TC_BMP_STRETCH: + if(desc->flags==TC_BMPF_IN) + strcpy(tempbuffer,"Stretch_in"); + else + strcpy(tempbuffer,"Stretch_out"); + break; + default: + strcpy(tempbuffer,"None"); + break; + } + + char masksetstr[256],maskunsetstr[256]; + masksetstr[0] = '\0'; maskunsetstr[0] = '\0'; + if(desc->mission_mask_set){ + BuildMissionFlagMask(desc->mission_mask_set,masksetstr,1); + } + if(desc->mission_mask_unset){ + BuildMissionFlagMask(desc->mission_mask_unset,maskunsetstr,0); + } + + char no_render[32]; + if(desc->flags&TC_NOEARLYRENDER) + strcpy(no_render,"no_early_rend"); + else + *no_render = '\0'; + + sprintf(buffer,"$bitmap effect %s starttime %.3f %s speed %.3f position %d,%d %s %s desc \"%s\" show \"%s\"",tempbuffer, + desc->waittime,no_render,desc->speed,desc->x,desc->y,masksetstr,maskunsetstr,effects[curr_effect].description,desc->filename); + cf_WriteString(file,buffer); + }break; + case BE_MOVIE: + { + LPTCMOVIEDESC desc = &effects[curr_effect].movie_desc; + if(desc->looping) + strcpy(tempbuffer,"looping"); + else + tempbuffer[0] = '\0'; + + char masksetstr[256],maskunsetstr[256]; + masksetstr[0] = '\0'; maskunsetstr[0] = '\0'; + if(desc->mission_mask_set){ + BuildMissionFlagMask(desc->mission_mask_set,masksetstr,1); + } + if(desc->mission_mask_unset){ + BuildMissionFlagMask(desc->mission_mask_unset,maskunsetstr,0); + } + + sprintf(buffer,"$movie position %d,%d fps %.3f %s starttime %.3f %s %s desc \"%s\" show \"%s\"",desc->x,desc->y, + desc->fps,tempbuffer,desc->waittime,masksetstr,maskunsetstr,effects[curr_effect].description,desc->filename); + cf_WriteString(file,buffer); + }break; + case BE_BKG: + { + Int3(); + }break; + case BE_POLY: + { + Int3(); + }break; + case BE_SND: + { + LPTCSNDDESC desc = &effects[curr_effect].snd_desc; + if(desc->once) + strcpy(tempbuffer,"once"); + else + tempbuffer[0]='\0'; + + char masksetstr[256],maskunsetstr[256]; + masksetstr[0] = '\0'; maskunsetstr[0] = '\0'; + if(desc->mission_mask_set){ + BuildMissionFlagMask(desc->mission_mask_set,masksetstr,1); + } + if(desc->mission_mask_unset){ + BuildMissionFlagMask(desc->mission_mask_unset,maskunsetstr,0); + } + + sprintf(buffer,"$sound %s starttime %.3f %s %s desc \"%s\" play \"%s\"",tempbuffer,desc->waittime,masksetstr,maskunsetstr,effects[curr_effect].description,desc->filename); + cf_WriteString(file,buffer); + }break; + case BE_BUTTON: + { + LPTCBUTTONDESC desc = &effects[curr_effect].button_desc; + char ctype[20]; + + switch(desc->click_type){ + case CLICKTYPE_CLICKDOWN: + strcpy(ctype,"ClickDown"); + break; + case CLICKTYPE_CLICKUP: + strcpy(ctype,"ClickUp"); + break; + case CLICKTYPE_DOWN: + strcpy(ctype,"HoldDown"); + break; + default: + strcpy(ctype,"ClickUp"); + break; + } + switch(desc->button_type){ + case BUTT_UPARROW: + strcpy(tempbuffer,"Up"); + break; + case BUTT_DOWNARROW: + strcpy(tempbuffer,"Down"); + break; + case BUTT_NEXTPAGE: + strcpy(tempbuffer,"Next"); + break; + case BUTT_PREVPAGE: + strcpy(tempbuffer,"Prev"); + break; + case BUTT_QUIT: + strcpy(tempbuffer,"Quit"); + break; + case BUTT_JUMP: + sprintf(tempbuffer,"Jump %d",desc->jump_page); + break; + default: + strcpy(tempbuffer,"Next"); + break; + } + + char flash_info[_MAX_PATH+256]; + flash_info[0] = '\0'; + if(desc->osflags&OBF_FLASH) + sprintf(flash_info,"flash %.3f \"%s\" \"%s\"",desc->flash_time,desc->flash_filename,desc->flash_filename_focus); + + char glow_fname[_MAX_PATH+4]; + glow_fname[0] = '\0'; + if(desc->osflags==OBF_GLOW) + sprintf(glow_fname,"\"%s\" \"%s\"",desc->flash_filename,desc->flash_filename_focus); + + char glow_id[7]; + glow_id[0] = '\0'; + if(desc->osflags&OBF_GLOW) + strcpy(glow_id,"glow"); + + char masksetstr[256],maskunsetstr[256]; + masksetstr[0] = '\0'; maskunsetstr[0] = '\0'; + if(desc->mission_mask_set){ + BuildMissionFlagMask(desc->mission_mask_set,masksetstr,1); + } + if(desc->mission_mask_unset){ + BuildMissionFlagMask(desc->mission_mask_unset,maskunsetstr,0); + } + + sprintf(buffer,"$button %d,%d type %s %s %s click %s id %d desc \"%s\" parent_id %d sibling_id %d %s %s show \"%s\" \"%s\" %s",desc->x,desc->y,tempbuffer, + flash_info,glow_id,ctype,effects[curr_effect].id,effects[curr_effect].description,desc->parent_id,desc->sibling_id,masksetstr,maskunsetstr, + desc->filename,desc->filename_focus,glow_fname); + cf_WriteString(file,buffer); + }break; + default: + Int3(); + break; + } + + curr_effect = effects[curr_effect].next; + } + + //Write out End screen + cf_WriteString(file,"$endscreen\n"); + + curr_screen = Briefing_screens[curr_screen].next; + screen_count++; + } + + cfclose(file); + return 1; +} + + +struct{ + int current_screen; + char title[128]; + CComboBox *scombo,*ecombo; + BriefGlobalValues *glob; +}BEParseInfo; + +void BEGetCurScreenEffect(int *ret_screen,int *ret_effect) +{ + if(ret_screen) + *ret_screen = -1; + if(ret_effect) + *ret_effect = -1; + + // Get the current screen + int curr_screen = BEParseInfo.scombo->GetCurSel(); + if(curr_screen==CB_ERR){ + return; + } + + //now we need to get the real effect num + int node = Briefing_root_screen; + int count = curr_screen; + + while(node!=-1 && count>0){ + count--; + node = Briefing_screens[node].next; + } + + ASSERT(count==0); //we better be at 0 here + ASSERT(node>=0 && nodeGetCurSel(); + if(curr_effect==CB_ERR){ + return; + } + + //now we need to get the real effect num + node = Briefing_screens[curr_screen].root_effect; + count = curr_effect; + + while(node!=-1 && count>0){ + count--; + node = Briefing_screens[curr_screen].effects[node].next; + } + + ASSERT(count==0); //we better be at 0 here + if(count!=0) + return; + + if(ret_effect) + *ret_effect = node; +} + +bool BEAllocEffect(int *ret_screen,int *ret_effect) +{ + // Get the current screen + int curr_screen; + BEGetCurScreenEffect(&curr_screen,NULL); + if(curr_screen==-1){ + return false; + } + + ASSERT(curr_screen>=0 && curr_screeneffects[i].used){ + curr_effect = i; + break; + } + } + if(curr_effect==-1){ + //no available effects + return false; + } + + bscr->effects[i].used = true; + if(node==-1){ + //first effect for screen + bscr->root_effect = curr_effect; + bscr->effects[curr_effect].prev = bscr->effects[curr_effect].next = -1; + *ret_screen = curr_screen; + *ret_effect = curr_effect; + return true; + }else{ + //get to the end of effects for list + while(bscr->effects[node].next!=-1){ + node = bscr->effects[node].next; + } + + //when we get here node should at the end of the list + bscr->effects[node].next = curr_effect; + bscr->effects[curr_effect].next = -1; + bscr->effects[curr_effect].prev = node; + *ret_screen = curr_screen; + *ret_effect = curr_effect; + return true; + } + + Int3(); + return false; //unknown error +} + +void BEAddTextEffect(LPTCTEXTDESC desc,char *text,char *description,int id) +{ + int curr_screen,curr_effect; + if(!BEAllocEffect(&curr_screen,&curr_effect)) + return; + + tBriefScreen *bscr = &Briefing_screens[curr_screen]; + tBriefEffect *befx = &bscr->effects[curr_effect]; + LPTCTEXTDESC dest = &befx->text_desc; + + if(strlen(description)==0) + strcpy(description,"Text"); + befx->type = BE_TEXT; + strcpy(befx->description,description); + befx->id = id; + + dest->caps = desc->caps; + memcpy(&dest->textbox,&desc->textbox,sizeof(tc_text)); + dest->font = desc->font; + dest->color = desc->color; + dest->flags = desc->flags; + dest->speed = desc->speed; + dest->looping = desc->looping; + dest->waittime = desc->waittime; + dest->type = desc->type; + dest->mission_mask_set = desc->mission_mask_set; + dest->mission_mask_unset = desc->mission_mask_unset; + + if(befx->text){ + mem_free(befx->text); + befx->text = NULL; + } + befx->text = (char *)mem_malloc(strlen(text)+1); + ASSERT(befx->text); + strcpy(befx->text,text); + + //Setup for items not set with caps + if(!(dest->caps&TCTD_FONT)){ + dest->caps |= TCTD_FONT; + dest->font = BRIEF_FONT_INDEX; + } + if(!(dest->caps&TCTD_COLOR)){ + dest->caps |= TCTD_COLOR; + dest->color = GR_GREEN; + } + if(!(dest->caps&TCTD_SPEED)){ + dest->caps |= TCTD_SPEED; + dest->speed = 1; + } + if(!(dest->caps&TCTD_LOOPING)){ + dest->caps |= TCTD_LOOPING; + dest->looping = false; + } + if(!(dest->caps&TCTD_WAITTIME)){ + dest->caps |= TCTD_WAITTIME; + dest->waittime = 0; + } + if(!(dest->caps&TCTD_TEXTBOX)){ + dest->caps |= TCTD_TEXTBOX; + dest->textbox.left = dest->textbox.top = 0; + dest->textbox.right = 639; + dest->textbox.bottom = 479; + } + +} + +void BEAddBmpEffect(LPTCBMPDESC desc,char *description) +{ + int curr_screen,curr_effect; + if(!BEAllocEffect(&curr_screen,&curr_effect)) + return; + + tBriefScreen *bscr = &Briefing_screens[curr_screen]; + tBriefEffect *befx = &bscr->effects[curr_effect]; + LPTCBMPDESC dest = &befx->bmp_desc; + + if(strlen(description)==0) + strcpy(description,"Bitmap"); + befx->type = BE_BMP; + strcpy(befx->description,description); + + dest->type = desc->type; + dest->flags = desc->flags; + dest->caps = desc->caps; + dest->x = desc->x; + dest->y = desc->y; + dest->looping = desc->looping; + dest->waittime = desc->waittime; + dest->speed = desc->speed; + dest->mission_mask_set = desc->mission_mask_set; + dest->mission_mask_unset = desc->mission_mask_unset; + strcpy(dest->filename,desc->filename); + + //Setup values not set with caps + if(!(dest->caps&TCBD_XY)){ + dest->caps |= TCBD_XY; + dest->x = dest->y = 0; + } + if(!(dest->caps&TCBD_LOOPING)){ + dest->caps |= TCBD_LOOPING; + dest->looping = false; + } + if(!(dest->caps&TCBD_WAITTIME)){ + dest->caps |= TCBD_WAITTIME; + dest->waittime = 0; + } + if(!(dest->caps&TCBD_SPEED)){ + dest->caps |= TCBD_SPEED; + dest->speed = 2; + } +} + +void BEAddMovieEffect(LPTCMOVIEDESC desc,char *description) +{ + int curr_screen,curr_effect; + if(!BEAllocEffect(&curr_screen,&curr_effect)) + return; + + tBriefScreen *bscr = &Briefing_screens[curr_screen]; + tBriefEffect *befx = &bscr->effects[curr_effect]; + LPTCMOVIEDESC dest = &befx->movie_desc; + + if(strlen(description)==0) + strcpy(description,"Movie"); + befx->type = BE_MOVIE; + strcpy(befx->description,description); + + dest->caps = desc->caps; + dest->type = desc->type; + dest->x = desc->x; + dest->y = desc->y; + dest->mission_mask_set = desc->mission_mask_set; + dest->mission_mask_unset = desc->mission_mask_unset; + strcpy(dest->filename,desc->filename); + dest->looping = desc->looping; + dest->fps = desc->fps; + dest->waittime = desc->waittime; + + //Setup values without caps + if(!(dest->caps&TCMD_XY)){ + dest->caps |= TCMD_XY; + dest->x = dest->y = 0; + } + if(!(dest->caps&TCMD_LOOPING)){ + dest->caps |= TCMD_LOOPING; + dest->looping = false; + } + if(!(dest->caps&TCMD_WAITTIME)){ + dest->caps |= TCMD_WAITTIME; + dest->waittime = 0; + } + if(!(dest->caps&TCMD_FPS)){ + dest->caps |= TCMD_FPS; + dest->fps = 20; + } +} + +void BEAddBkgEffect(LPTCBKGDESC desc,char *description) +{ + int curr_screen,curr_effect; + if(!BEAllocEffect(&curr_screen,&curr_effect)) + return; + + tBriefScreen *bscr = &Briefing_screens[curr_screen]; + tBriefEffect *befx = &bscr->effects[curr_effect]; + LPTCBKGDESC dest = &befx->bkg_desc; + + if(strlen(description)==0) + strcpy(description,"Background"); + befx->type = BE_BKG; + strcpy(befx->description,description); + + dest->caps = desc->caps; + dest->type = desc->type; + dest->id = desc->id; + dest->color = desc->color; + dest->waittime = desc->waittime; + dest->mission_mask_set = desc->mission_mask_set; + dest->mission_mask_unset = desc->mission_mask_unset; + + //setup values without caps + if(!(dest->caps&TCBGD_ID)){ + dest->caps |= TCBGD_ID; + dest->id = 0; + } + if(!(dest->caps&TCBGD_WAITTIME)){ + dest->caps |= TCBGD_WAITTIME; + dest->waittime = 0; + } + if(!(dest->caps&TCBGD_COLOR)){ + dest->caps |= TCBGD_COLOR; + dest->color = GR_BLUE; + } +} + +void BEAddPolyEffect(LPTCPOLYDESC desc,char *description) +{ + int curr_screen,curr_effect; + if(!BEAllocEffect(&curr_screen,&curr_effect)) + return; + + tBriefScreen *bscr = &Briefing_screens[curr_screen]; + tBriefEffect *befx = &bscr->effects[curr_effect]; + LPTCPOLYDESC dest = &befx->poly_desc; + + if(strlen(description)==0) + strcpy(description,"PolyModel"); + befx->type = BE_POLY; + strcpy(befx->description,description); + + dest->caps = desc->caps; + dest->type = desc->type; + dest->pos_x = desc->pos_x; + dest->pos_y = desc->pos_y; + dest->pos_z = desc->pos_z; + dest->rot_x = desc->rot_x; + dest->rot_y = desc->rot_y; + dest->rot_z = desc->rot_z; + dest->ori_x = desc->ori_x; + dest->ori_y = desc->ori_y; + dest->ori_z = desc->ori_z; + dest->flags = desc->flags; + dest->waittime = desc->waittime; + dest->mission_mask_set = desc->mission_mask_set; + dest->mission_mask_unset = desc->mission_mask_unset; + strcpy(dest->polyname,desc->polyname); + + Int3(); //Why are we here!?!?!?? This effect isn't even in yet + if(!(dest->caps&TCPM_SPEED)){ + dest->caps |= TCPM_SPEED; + dest->waittime = 0; + } +} + +void BEAddSoundEffect(LPTCSNDDESC desc,char *description) +{ + int curr_screen,curr_effect; + if(!BEAllocEffect(&curr_screen,&curr_effect)) + return; + + tBriefScreen *bscr = &Briefing_screens[curr_screen]; + tBriefEffect *befx = &bscr->effects[curr_effect]; + LPTCSNDDESC dest = &befx->snd_desc; + + if(strlen(description)==0) + strcpy(description,"Sound"); + befx->type = BE_SND; + strcpy(befx->description,description); + + dest->caps = desc->caps; + dest->type = desc->type; + dest->once = desc->once; + dest->waittime = desc->waittime; + dest->mission_mask_set = desc->mission_mask_set; + dest->mission_mask_unset = desc->mission_mask_unset; + strcpy(dest->filename,desc->filename); + + //Setup values without caps + if(!(dest->caps&TCSD_WAITTIME)){ + dest->caps |= TCSD_WAITTIME; + dest->waittime = 0; + } + if(!(dest->caps&TCSD_ONCE)){ + dest->caps |= TCSD_ONCE; + dest->once = true; + } +} + +void BEAddButtonEffect(LPTCBUTTONDESC desc,char *description,int id) +{ + int curr_screen,curr_effect; + if(!BEAllocEffect(&curr_screen,&curr_effect)) + return; + + tBriefScreen *bscr = &Briefing_screens[curr_screen]; + tBriefEffect *befx = &bscr->effects[curr_effect]; + LPTCBUTTONDESC dest = &befx->button_desc; + + if(strlen(description)==0) + strcpy(description,"Button"); + befx->type = BE_BUTTON; + strcpy(befx->description,description); + befx->id = id; + + strcpy(dest->filename,desc->filename); + strcpy(dest->filename_focus,desc->filename_focus); + if(desc->flasher){ + strcpy(dest->flash_filename,desc->flash_filename); + strcpy(dest->flash_filename_focus,desc->flash_filename_focus); + }else{ + dest->flash_filename[0]='\0'; + dest->flash_filename_focus[0]='\0'; + } + dest->sibling_id = desc->sibling_id; + dest->parent_id = desc->parent_id; + dest->x = desc->x; + dest->y = desc->y; + dest->w = desc->w; + dest->h = desc->h; + dest->osflags = desc->osflags; + dest->flash_time = desc->flash_time; + dest->button_type = desc->button_type; + dest->click_type = desc->click_type; + dest->flasher = desc->flasher; + dest->mission_mask_set = desc->mission_mask_set; + dest->mission_mask_unset = desc->mission_mask_unset; + dest->jump_page = desc->jump_page; +} + +void BEStartScreen(int screen_num,char *description,char *layout,uint mask_set,uint mask_unset) +{ + int scr_to_add = -1; + for(int i=0;iAddString(description); + ASSERT(sel>=0); + BEParseInfo.scombo->SetCurSel(sel); +} + +void BEEndScreen() +{ +} + +void BESetTitle(char *title) +{ + strcpy(BEParseInfo.glob->title,title); +} + +void BESetStatic(float amount) +{ + BEParseInfo.glob->static_val = amount; +} + +void BESetGlitch(float amount) +{ + BEParseInfo.glob->glitch_val = amount; +} + +void BEAddVoice(char *filename,int flags,char *description) +{ +} + +// BriefEditLoadScreens +// +// Loads in screens from a briefing file +ubyte BriefEditLoadScreens(char *filename,CComboBox *screen_combo,CComboBox *effect_combo,BriefGlobalValues *glob) +{ + BEParseInfo.current_screen = 0; + BEParseInfo.title[0] = '\0'; + BEParseInfo.scombo = screen_combo; + BEParseInfo.ecombo = effect_combo; + BEParseInfo.glob = glob; + + glob->title[0] = '\0'; + glob->static_val = glob->glitch_val = 0; + + CBriefParse engine; + tBriefParseCallbacks pb_callbacks; + + pb_callbacks.AddTextEffect = BEAddTextEffect; + pb_callbacks.AddBmpEffect = BEAddBmpEffect; + pb_callbacks.AddMovieEffect = BEAddMovieEffect; + pb_callbacks.AddBkgEffect = BEAddBkgEffect; + pb_callbacks.AddPolyEffect = BEAddPolyEffect; + pb_callbacks.AddSoundEffect = BEAddSoundEffect; + pb_callbacks.AddButtonEffect = BEAddButtonEffect; + pb_callbacks.StartScreen = BEStartScreen; + pb_callbacks.EndScreen = BEEndScreen; + pb_callbacks.LoopCallback = NULL; + pb_callbacks.SetTitle = BESetTitle; + pb_callbacks.SetStatic = BESetStatic; + pb_callbacks.SetGlitch = BESetGlitch; + pb_callbacks.AddVoice = BEAddVoice; + + engine.SetCallbacks(&pb_callbacks); + return engine.ParseBriefing(filename); +} + +// BriefEditAllocateEffect +// +// Allocates an effect (links it and all) to be edited. Returns false on error +bool CBriefEdit::BriefEditAllocateEffect(int *ret_screen,int *ret_effect) +{ + UpdateData(true); + + // Get the current screen + int curr_screen; + BriefEditGetCurScreenEffect(&curr_screen,NULL); + if(curr_screen==-1){ + MessageBox("You Need To Create A Screen","Error"); + return false; + } + + ASSERT(curr_screen>=0 && curr_screeneffects[i].used){ + curr_effect = i; + break; + } + } + if(curr_effect==-1){ + //no available effects + MessageBox("No More Effects Available For This Screen","Error"); + return false; + } + + bscr->effects[i].used = true; + if(node==-1){ + //first effect for screen + bscr->root_effect = curr_effect; + bscr->effects[curr_effect].prev = bscr->effects[curr_effect].next = -1; + *ret_screen = curr_screen; + *ret_effect = curr_effect; + return true; + }else{ + //get to the end of effects for list + while(bscr->effects[node].next!=-1){ + node = bscr->effects[node].next; + } + + //when we get here node should at the end of the list + bscr->effects[node].next = curr_effect; + bscr->effects[curr_effect].next = -1; + bscr->effects[curr_effect].prev = node; + *ret_screen = curr_screen; + *ret_effect = curr_effect; + return true; + } + + Int3(); + return false; //unknown error +} + +// BriefEditGetCurScreenEffect +// +// Fills in the current screen and effect that is being worked on +void CBriefEdit::BriefEditGetCurScreenEffect(int *ret_screen,int *ret_effect) +{ + if(ret_screen) + *ret_screen = -1; + if(ret_effect) + *ret_effect = -1; + + UpdateData(true); + + // Get the current screen + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_SCREEN_LIST); + int curr_screen = combo->GetCurSel(); + if(curr_screen==CB_ERR){ + return; + } + + //now we need to get the real effect num + int node = Briefing_root_screen; + int count = curr_screen; + + while(node!=-1 && count>0){ + count--; + node = Briefing_screens[node].next; + } + + ASSERT(count==0); //we better be at 0 here + ASSERT(node>=0 && nodeGetCurSel(); + if(curr_effect==CB_ERR){ + return; + } + + //now we need to get the real effect num + node = Briefing_screens[curr_screen].root_effect; + count = curr_effect; + + while(node!=-1 && count>0){ + count--; + node = Briefing_screens[curr_screen].effects[node].next; + } + +// ASSERT(count==0); //we better be at 0 here + if(count!=0) + return; + + if(ret_effect) + *ret_effect = node; +} + +///////////////////////////////////////////////////////////////////////////// +// CBriefEdit message handlers + +void CBriefEdit::OnOK() +{ + if(has_changed) + { + //they've made changes but haven't saved + if(MessageBox("You haven't saved your changes, are you sure you want to quit?","Confirm",MB_YESNO)!=IDYES) + { + return; + } + } + + has_changed = false; + + if(layouts) + mem_free(layouts); + if(layout_bmp>BAD_BITMAP_HANDLE) + bm_FreeBitmap(layout_bmp); + CDialog::OnOK(); +} + +void CBriefEdit::OnBriefEffectBitmap() +{ + int curr; + BriefEditGetCurScreenEffect(&curr,NULL); + + CBriefBitmapEdit dlg(curr); + if(dlg.DoModal()==IDOK){ + has_changed = true; + int c_scr,c_eff; + if(!BriefEditAllocateEffect(&c_scr,&c_eff)) + return; + + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_EFFECT_LIST); + int sel = combo->AddString(dlg.m_sDesc); + ASSERT(sel>=0); //out of memory!? + combo->SetCurSel(sel); + Briefing_screens[c_scr].effects[c_eff].type = BE_BMP; + strncpy(Briefing_screens[c_scr].effects[c_eff].description,dlg.m_sDesc.GetBuffer(1),127); + Briefing_screens[c_scr].effects[c_eff].description[127]='\0'; + + //retrieve info + LPTCBMPDESC dest = &Briefing_screens[c_scr].effects[c_eff].bmp_desc; + LPTCBMPDESC src = &dlg.desc; + + dest->type = src->type; + dest->flags = src->flags; + dest->caps = src->caps; + dest->x = src->x; + dest->y = src->y; + dest->looping = src->looping; + dest->waittime = src->waittime; + dest->speed = src->speed; + dest->mission_mask_set = src->mission_mask_set; + dest->mission_mask_unset = src->mission_mask_unset; + strcpy(dest->filename,src->filename); + } +} + +void CBriefEdit::OnBriefEffectButton() +{ + CBriefButtonEdit dlg; + if(dlg.DoModal()==IDOK){ + has_changed = true; + int c_scr,c_eff; + if(!BriefEditAllocateEffect(&c_scr,&c_eff)) + return; + + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_EFFECT_LIST); + int sel = combo->AddString(dlg.m_sDesc); + ASSERT(sel>=0); //out of memory!? + combo->SetCurSel(sel); + Briefing_screens[c_scr].effects[c_eff].type = BE_BUTTON; + strncpy(Briefing_screens[c_scr].effects[c_eff].description,dlg.m_sDesc.GetBuffer(1),127); + Briefing_screens[c_scr].effects[c_eff].description[127]='\0'; + + //retrieve info + LPTCBUTTONDESC dest = &Briefing_screens[c_scr].effects[c_eff].button_desc; + LPTCBUTTONDESC src = &dlg.desc; + + strcpy(dest->filename,src->filename); + strcpy(dest->filename_focus,src->filename_focus); + strcpy(dest->flash_filename,src->flash_filename); + strcpy(dest->flash_filename_focus,src->flash_filename_focus); + dest->sibling_id = src->sibling_id; + dest->parent_id = src->parent_id; + dest->x = src->x; + dest->y = src->y; + dest->w = src->w; + dest->h = src->h; + dest->osflags = src->osflags; + dest->flash_time = src->flash_time; + dest->button_type = src->button_type; + dest->click_type = src->click_type; + dest->flasher = src->flasher; + dest->mission_mask_set = src->mission_mask_set; + dest->mission_mask_unset = src->mission_mask_unset; + dest->jump_page = src->jump_page; + + Briefing_screens[c_scr].effects[c_eff].id = dlg.m_iID; + } +} + +void CBriefEdit::OnBriefEffectDel() +{ + UpdateData(true); + int curr_screen,curr_effect; + BriefEditGetCurScreenEffect(&curr_screen,&curr_effect); + if(curr_screen == -1 || curr_effect == -1){ + MessageBox("No Effects To Delete","Error"); + return; + } + + if(MessageBox("Are You Sure You Want To Delete Effect?","Confirmation",MB_YESNO)!=IDYES) + return; + + ASSERT( curr_screen>=0 && curr_screen=0 && curr_effecteffects[curr_effect].prev; + int next = bscr->effects[curr_effect].next; + + if(prev==-1) + bscr->root_effect = next; + else + bscr->effects[prev].next = next; + + if(next!=-1) + bscr->effects[next].prev = prev; + + BriefEditFreeEffect(&bscr->effects[curr_effect]); + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_EFFECT_LIST); + combo->DeleteString(combo->GetCurSel()); + combo->SetCurSel(0); + has_changed = true; + UpdateData(false); +} + +void CBriefEdit::OnBriefEffectEdit() +{ + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_EFFECT_LIST); + int curr_effect = combo->GetCurSel(); + + int efx_index,scr_index; + BriefEditGetCurScreenEffect(&scr_index,&efx_index); + + if(scr_index==-1 || efx_index==-1){ + MessageBox("No Effects To Edit","Error"); + return; + } + + tBriefEffect *efx = &Briefing_screens[scr_index].effects[efx_index]; + + switch(efx->type){ + case BE_TEXT: + { + CBriefTextEdit dlg(scr_index,&efx->text_desc,efx->text,efx->id); + combo->GetLBText(curr_effect,dlg.m_sDesc); + if(dlg.DoModal()==IDOK){ + has_changed = true; + //grab the information from the dialog + combo->DeleteString(curr_effect); + combo->InsertString(curr_effect,dlg.m_sDesc); + combo->SetCurSel(curr_effect); + strncpy(Briefing_screens[scr_index].effects[efx_index].description,dlg.m_sDesc.GetBuffer(1),127); + Briefing_screens[scr_index].effects[efx_index].description[127]='\0'; + + //retrieve info + LPTCTEXTDESC dest = &Briefing_screens[scr_index].effects[efx_index].text_desc; + LPTCTEXTDESC src = &dlg.desc; + + dest->caps = src->caps; + memcpy(&dest->textbox,&src->textbox,sizeof(tc_text)); + dest->font = src->font; + dest->color = src->color; + dest->flags = src->flags; + dest->speed = src->speed; + dest->looping = src->looping; + dest->waittime = src->waittime; + dest->type = src->type; + dest->mission_mask_set = src->mission_mask_set; + dest->mission_mask_unset = src->mission_mask_unset; + + + Briefing_screens[scr_index].effects[efx_index].id = dlg.m_iID; + + if(Briefing_screens[scr_index].effects[efx_index].text) + mem_free(Briefing_screens[scr_index].effects[efx_index].text); + + Briefing_screens[scr_index].effects[efx_index].text = (char *)mem_malloc(dlg.m_Text.GetLength()+1); + ASSERT(Briefing_screens[scr_index].effects[efx_index].text); + + if(Briefing_screens[scr_index].effects[efx_index].text){ + strcpy(Briefing_screens[scr_index].effects[efx_index].text,dlg.m_Text.GetBuffer(1)); + } + } + }break; + case BE_BMP: + { + CBriefBitmapEdit dlg(scr_index,&efx->bmp_desc); + combo->GetLBText(curr_effect,dlg.m_sDesc); + if(dlg.DoModal()==IDOK){ + has_changed = true; + //grab the information from the dialog + combo->DeleteString(curr_effect); + combo->InsertString(curr_effect,dlg.m_sDesc); + combo->SetCurSel(curr_effect); + strncpy(Briefing_screens[scr_index].effects[efx_index].description,dlg.m_sDesc.GetBuffer(1),127); + Briefing_screens[scr_index].effects[efx_index].description[127]='\0'; + + //retrieve info + LPTCBMPDESC dest = &Briefing_screens[scr_index].effects[efx_index].bmp_desc; + LPTCBMPDESC src = &dlg.desc; + + dest->type = src->type; + dest->flags = src->flags; + dest->caps = src->caps; + dest->x = src->x; + dest->y = src->y; + dest->looping = src->looping; + dest->waittime = src->waittime; + dest->speed = src->speed; + dest->mission_mask_set = src->mission_mask_set; + dest->mission_mask_unset = src->mission_mask_unset; + + strcpy(dest->filename,src->filename); + + } + }break; + case BE_MOVIE: + { + CBriefMovieEdit dlg(&efx->movie_desc); + combo->GetLBText(curr_effect,dlg.m_sDesc); + if(dlg.DoModal()==IDOK){ + has_changed = true; + //grab the information from the dialog + combo->DeleteString(curr_effect); + combo->InsertString(curr_effect,dlg.m_sDesc); + combo->SetCurSel(curr_effect); + strncpy(Briefing_screens[scr_index].effects[efx_index].description,dlg.m_sDesc.GetBuffer(1),127); + Briefing_screens[scr_index].effects[efx_index].description[127]='\0'; + + //retrieve info + LPTCMOVIEDESC dest = &Briefing_screens[scr_index].effects[efx_index].movie_desc; + LPTCMOVIEDESC src = &dlg.desc; + + dest->caps = src->caps; + dest->type = src->type; + dest->x = src->x; + dest->y = src->y; + strcpy(dest->filename,src->filename); + dest->looping = src->looping; + dest->fps = src->fps; + dest->waittime = src->waittime; + dest->mission_mask_set = src->mission_mask_set; + dest->mission_mask_unset = src->mission_mask_unset; + + } + }break; + case BE_BKG: + break; + case BE_POLY: + break; + case BE_SND: + { + CBriefSoundEdit dlg(&efx->snd_desc); + combo->GetLBText(curr_effect,dlg.m_sDesc); + if(dlg.DoModal()==IDOK){ + has_changed = true; + //grab the information from the dialog + combo->DeleteString(curr_effect); + combo->InsertString(curr_effect,dlg.m_sDesc); + combo->SetCurSel(curr_effect); + strncpy(Briefing_screens[scr_index].effects[efx_index].description,dlg.m_sDesc.GetBuffer(1),127); + Briefing_screens[scr_index].effects[efx_index].description[127]='\0'; + + //retrieve info + LPTCSNDDESC dest = &Briefing_screens[scr_index].effects[efx_index].snd_desc; + LPTCSNDDESC src = &dlg.desc; + + dest->caps = src->caps; + dest->type = src->type; + dest->once = src->once; + dest->waittime = src->waittime; + dest->mission_mask_set = src->mission_mask_set; + dest->mission_mask_unset = src->mission_mask_unset; + strcpy(dest->filename,src->filename); + } + }break; + case BE_BUTTON: + { + CBriefButtonEdit dlg(&efx->button_desc,efx->id); + combo->GetLBText(curr_effect,dlg.m_sDesc); + if(dlg.DoModal()==IDOK){ + has_changed = true; + //grab the information from the dialog + combo->DeleteString(curr_effect); + combo->InsertString(curr_effect,dlg.m_sDesc); + combo->SetCurSel(curr_effect); + strncpy(Briefing_screens[scr_index].effects[efx_index].description,dlg.m_sDesc.GetBuffer(1),127); + Briefing_screens[scr_index].effects[efx_index].description[127]='\0'; + + //retrieve info + LPTCBUTTONDESC dest = &Briefing_screens[scr_index].effects[efx_index].button_desc; + LPTCBUTTONDESC src = &dlg.desc; + + strcpy(dest->filename,src->filename); + strcpy(dest->filename_focus,src->filename_focus); + strcpy(dest->flash_filename,src->flash_filename); + strcpy(dest->flash_filename_focus,src->flash_filename_focus); + dest->sibling_id = src->sibling_id; + dest->parent_id = src->parent_id; + dest->x = src->x; + dest->y = src->y; + dest->w = src->w; + dest->h = src->h; + dest->osflags = src->osflags; + dest->flash_time = src->flash_time; + dest->button_type = src->button_type; + dest->click_type = src->click_type; + dest->flasher = src->flasher; + dest->mission_mask_set = src->mission_mask_set; + dest->mission_mask_unset = src->mission_mask_unset; + dest->jump_page = src->jump_page; + + Briefing_screens[scr_index].effects[efx_index].id = dlg.m_iID; + } + }break; + default: + Int3(); + return; + break; + } + +} + +void CBriefEdit::OnBriefEffectMovie() +{ + CBriefMovieEdit dlg; + if(dlg.DoModal()==IDOK){ + has_changed = true; + int c_scr,c_eff; + if(!BriefEditAllocateEffect(&c_scr,&c_eff)) + return; + + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_EFFECT_LIST); + int sel = combo->AddString(dlg.m_sDesc); + ASSERT(sel>=0); //out of memory!? + combo->SetCurSel(sel); + Briefing_screens[c_scr].effects[c_eff].type = BE_MOVIE; + strncpy(Briefing_screens[c_scr].effects[c_eff].description,dlg.m_sDesc.GetBuffer(1),127); + Briefing_screens[c_scr].effects[c_eff].description[127]='\0'; + + //retrieve info + LPTCMOVIEDESC dest = &Briefing_screens[c_scr].effects[c_eff].movie_desc; + LPTCMOVIEDESC src = &dlg.desc; + + dest->caps = src->caps; + dest->type = src->type; + dest->x = src->x; + dest->y = src->y; + strcpy(dest->filename,src->filename); + dest->looping = src->looping; + dest->fps = src->fps; + dest->waittime = src->waittime; + dest->mission_mask_set = src->mission_mask_set; + dest->mission_mask_unset = src->mission_mask_unset; + + } +} + +void CBriefEdit::OnBriefEffectSound() +{ + CBriefSoundEdit dlg; + if(dlg.DoModal()==IDOK){ + has_changed = true; + int c_scr,c_eff; + if(!BriefEditAllocateEffect(&c_scr,&c_eff)) + return; + + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_EFFECT_LIST); + int sel = combo->AddString(dlg.m_sDesc); + ASSERT(sel>=0); //out of memory!? + combo->SetCurSel(sel); + Briefing_screens[c_scr].effects[c_eff].type = BE_SND; + strncpy(Briefing_screens[c_scr].effects[c_eff].description,dlg.m_sDesc.GetBuffer(1),127); + Briefing_screens[c_scr].effects[c_eff].description[127]='\0'; + + //retrieve info + LPTCSNDDESC dest = &Briefing_screens[c_scr].effects[c_eff].snd_desc; + LPTCSNDDESC src = &dlg.desc; + + dest->caps = src->caps; + dest->type = src->type; + dest->once = src->once; + dest->waittime = src->waittime; + dest->mission_mask_set = src->mission_mask_set; + dest->mission_mask_unset = src->mission_mask_unset; + + strcpy(dest->filename,src->filename); + } +} + +void CBriefEdit::OnBriefEffectText() +{ + int curr; + BriefEditGetCurScreenEffect(&curr,NULL); + + CBriefTextEdit dlg(curr); + if(dlg.DoModal()==IDOK){ + has_changed = true; + int c_scr,c_eff; + if(!BriefEditAllocateEffect(&c_scr,&c_eff)) + return; + + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_EFFECT_LIST); + int sel = combo->AddString(dlg.m_sDesc); + ASSERT(sel>=0); //out of memory!? + combo->SetCurSel(sel); + Briefing_screens[c_scr].effects[c_eff].type = BE_TEXT; + strncpy(Briefing_screens[c_scr].effects[c_eff].description,dlg.m_sDesc.GetBuffer(1),127); + Briefing_screens[c_scr].effects[c_eff].description[127]='\0'; + + //retrieve info + LPTCTEXTDESC dest = &Briefing_screens[c_scr].effects[c_eff].text_desc; + LPTCTEXTDESC src = &dlg.desc; + + dest->caps = src->caps; + memcpy(&dest->textbox,&src->textbox,sizeof(tc_text)); + dest->font = src->font; + dest->color = src->color; + dest->flags = src->flags; + dest->speed = src->speed; + dest->looping = src->looping; + dest->waittime = src->waittime; + dest->type = src->type; + dest->mission_mask_set = src->mission_mask_set; + dest->mission_mask_unset = src->mission_mask_unset; + + Briefing_screens[c_scr].effects[c_eff].id = dlg.m_iID; + + if(Briefing_screens[c_scr].effects[c_eff].text) + mem_free(Briefing_screens[c_scr].effects[c_eff].text); + + Briefing_screens[c_scr].effects[c_eff].text = (char *)mem_malloc(dlg.m_Text.GetLength()+1); + ASSERT(Briefing_screens[c_scr].effects[c_eff].text); + + if(Briefing_screens[c_scr].effects[c_eff].text){ + strcpy(Briefing_screens[c_scr].effects[c_eff].text,dlg.m_Text.GetBuffer(1)); + } + } +} + +void CBriefEdit::OnBriefScreenAdd() +{ + CBriefScreenEdit dlg; + + if(dlg.DoModal()==IDOK){ + has_changed = true; + int scr_to_add = -1; + + for(int i=0;iAddString(dlg.m_sDesc); + ASSERT(sel>=0); + combo->SetCurSel(sel); + OnSelchangeBriefScreenList(); + UpdateLayoutBitmap(); + mprintf((0,"Added a screen\n")); + } +} + +void CBriefEdit::OnBriefScreenDel() +{ + UpdateData(true); + int curr_screen; + BriefEditGetCurScreenEffect(&curr_screen,NULL); + if(curr_screen == -1){ + MessageBox("No Screens To Delete","Error"); + return; + } + + if(MessageBox("Are You Sure You Want To Delete Screen?","Confirmation",MB_YESNO)!=IDYES) + return; + + has_changed = true; + + int next,prev; + + ASSERT( curr_screen>=0 && curr_screenDeleteString(combo->GetCurSel()); + combo->SetCurSel(0); + OnSelchangeBriefScreenList(); + UpdateData(false); +} + +void CBriefEdit::OnBriefScreenEdit() +{ + UpdateData(true); + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_SCREEN_LIST); + int curr_screen = combo->GetCurSel(); + + int scr_index; + BriefEditGetCurScreenEffect(&scr_index,NULL); + + if(scr_index==-1){ + MessageBox("No Screens To Edit","Error"); + return; + } + + CBriefScreenEdit dlg(scr_index); + combo->GetLBText(curr_screen,dlg.m_sDesc); + + if(dlg.DoModal()==IDOK){ + has_changed = true; + //grab the information from the dialog + combo->DeleteString(curr_screen); + combo->InsertString(curr_screen,dlg.m_sDesc); + combo->SetCurSel(curr_screen); + + strcpy(Briefing_screens[scr_index].layout,dlg.layout_str.GetBuffer(1)); + Briefing_screens[scr_index].mission_mask_set = dlg.m_Set; + Briefing_screens[scr_index].mission_mask_unset = dlg.m_UnSet; + UpdateLayoutBitmap(); + } + UpdateData(false); +} + +void CBriefEdit::UpdateInfo() +{ +} + + +BOOL CBriefEdit::OnInitDialog() +{ + CDialog::OnInitDialog(); + + //Start the timer + CWnd::SetTimer(1,50,NULL); + + BriefEditInitScreens(); + + + UpdateInfo(); + has_changed = false; + + return TRUE; +} + +void CBriefEdit::OnDestroy() +{ + CDialog::OnDestroy(); + + BriefEditFreeScreens(); +} + +void CBriefEdit::OnSelchangeBriefScreenList() +{ + CComboBox *scr_combo = (CComboBox *)GetDlgItem(IDC_BRIEF_SCREEN_LIST); + CComboBox *eff_combo = (CComboBox *)GetDlgItem(IDC_BRIEF_EFFECT_LIST); + eff_combo->ResetContent(); + + int curr_screen; + + BriefEditGetCurScreenEffect(&curr_screen,NULL); + if(curr_screen==-1) + return; + + //now go through the new screen and add effects + int node = Briefing_screens[curr_screen].root_effect; + tBriefScreen *bscr = &Briefing_screens[curr_screen]; + while(node!=-1){ + switch(bscr->effects[node].type){ + case BE_TEXT: + case BE_BMP: + case BE_MOVIE: + case BE_BKG: + case BE_POLY: + case BE_SND: + case BE_BUTTON: + eff_combo->AddString(bscr->effects[node].description); + break; + default: + eff_combo->AddString("Unknown"); + break; + } + node = bscr->effects[node].next; + } + eff_combo->SetCurSel(0); + + UpdateLayoutBitmap(); +} + +void CBriefEdit::OnBriefSave() +{ + UpdateData(true); + char szFilter[] = "Descent3 Briefing Files (*.brf)|*.brf||"; + CFileDialog dlg(false,".brf",NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter); + + if(dlg.DoModal()==IDOK){ + has_changed = false; + m_GlobalValues.static_val = m_fStatic; + m_GlobalValues.glitch_val = m_fGlitch; + strcpy(m_GlobalValues.title,m_sTitle.GetBuffer(1)); + + BriefEditSaveScreens(dlg.GetPathName().GetBuffer(1),(CComboBox *)GetDlgItem(IDC_BRIEF_SCREEN_LIST),&m_GlobalValues); + } +} + +void CBriefEdit::OnLoad() +{ + char szFilter[] = "Descent3 Briefing Files (*.brf)|*.brf||"; + CFileDialog dlg(true,".brf",NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter); + + if(dlg.DoModal()==IDOK){ + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_SCREEN_LIST); + combo->ResetContent(); + BriefEditFreeScreens(); + BriefEditInitScreens(); + BriefEditLoadScreens(dlg.GetPathName().GetBuffer(1),combo,(CComboBox *)GetDlgItem(IDC_BRIEF_EFFECT_LIST),&m_GlobalValues); + + m_fStatic = m_GlobalValues.static_val; + m_fGlitch = m_GlobalValues.glitch_val; + m_sTitle = m_GlobalValues.title; + + UpdateData(false); + UpdateInfo(); + OnSelchangeBriefScreenList(); + UpdateLayoutBitmap(); + has_changed = false; + } +} + +void CBriefEdit::UpdateLayoutBitmap(void) +{ + int scr; + BriefEditGetCurScreenEffect(&scr,NULL); + if(scr==-1) + return; + + SetLayoutBitmap(Briefing_screens[scr].layout); +} + +void CBriefEdit::SetLayoutBitmap(char *filename) +{ + if(layout_bmp>BAD_BITMAP_HANDLE) + bm_FreeBitmap(layout_bmp); + + layout_bmp = -1; + + if(filename[0]!='\0') + layout_bmp = bm_AllocLoadFileBitmap(filename,0); + has_changed = true; +} + + +void CBriefEdit::ParseLayoutScreenFile(char *filename) +{ + CFILE *file = cfopen(filename,"rt"); + if(!file) + return; + + num_layouts = 0; + if(layouts){ + mem_free(layouts); + layouts = NULL; + } + + char buffer[512]; + + cf_ReadString(buffer,512,file); + num_layouts = atoi(buffer); + + if(num_layouts<=0){ + cfclose(file); + mprintf((0,"Zero or less Layout Screens in Layout File\n")); + return; + } + + layouts = (tLayoutScreen *)mem_malloc(sizeof(tLayoutScreen)*num_layouts); + if(!layouts){ + mprintf((0,"Out of memory loading layout screens...trying to load %d screens\n",num_layouts)); + num_layouts = 0; + cfclose(file); + return; + } + + memset(layouts,0,sizeof(tLayoutScreen)*num_layouts); + + //format of a layout def. + //--filename + //--number of text boxes + //--number of bmp boxes + //----textbox defs + //-----lx ty rx by + //----bmp defs + //-----x y + + for(int i=0;i=0 && layouts[i].num_texts=0 && layouts[i].num_bmps(bmw-1)) lx = bmw-1; + if(rx<0) rx = 0; + if(rx>(bmw-1)) rx = bmw-1; + if(ty<0) ty = 0; + if(ty>(bmh-1)) ty= bmh-1; + if(by<0) by = 0; + if(by>(bmh-1)) by=bmh-1; + + //vport->fillrect(color,lx,ty,rx,by); + vport->line(color,lx,ty,lx,by); + vport->line(color,rx,ty,rx,by); + vport->line(color,lx,ty,rx,ty); + vport->line(color,lx,by,rx,by); +} + +void CBriefEdit::UpdateView(void) +{ + CWnd *objwnd; + RECT rect; + int x,y,w,h; + + objwnd = GetDlgItem(IDC_BRIEF_PICTURE); + objwnd->GetWindowRect(&rect); + ScreenToClient(&rect); + + if(layout_bmp>BAD_BITMAP_HANDLE){ + bmw = bm_w(layout_bmp,0); + bmh = bm_h(layout_bmp,0); + }else{ + bmw = 640; + bmh = 480; + } + + static float age = 0; + static bool on = false; + static float last_time = 0; + + float t = timer_GetTime(); + float frametime = t - last_time; + last_time = t; + + age += frametime; + + if(age>0.5){ + on = !on; + age = 0; + } + + rend_StartFrame(0,0,bmw,bmh); + + Desktop_surf->attach_to_window((unsigned)m_hWnd); + + w=rect.right-rect.left; + h=rect.bottom-rect.top; + + static bool first_call = true; + + if(first_call) + Desktop_surf->clear(rect.left,rect.top,w,h); + + m_ObjectSurf.create(bmw, bmh, BPP_16); + + if(layout_bmp>BAD_BITMAP_HANDLE){ + m_ObjectSurf.load(layout_bmp); + }else + Desktop_surf->clear(rect.left,rect.top,w,h); + + grViewport *vport=new grViewport (&m_ObjectSurf); + vport->lock(); + + //now we need to go through all the effects in the screen and draw a rep of em + int curr_screen,curr_effect; + int node; + tBriefEffect *effects; + BriefEditGetCurScreenEffect(&curr_screen,&curr_effect); + + if(curr_screen!=-1){ + node = Briefing_screens[curr_screen].root_effect; + effects = Briefing_screens[curr_screen].effects; + + while(node!=-1){ + if(node==curr_effect && !on){ + }else{ + switch(effects[node].type){ + case BE_TEXT: + DrawRect(GR_RGB(255,40,255),effects[node].text_desc.textbox.left,effects[node].text_desc.textbox.top,effects[node].text_desc.textbox.right,effects[node].text_desc.textbox.bottom,vport); + break; + case BE_BMP: + { + if(effects[node].w==-1){ + //we need to set up values + int handle = bm_AllocLoadFileBitmap(effects[node].bmp_desc.filename,0); + if(handle>BAD_BITMAP_HANDLE){ + effects[node].w = bm_w(handle,0); + effects[node].h = bm_h(handle,0); + bm_FreeBitmap(handle); + }else{ + effects[node].w = effects[node].h = 16; + } + } + int x,y,w,h; + x = effects[node].bmp_desc.x; + y = effects[node].bmp_desc.y; + w = effects[node].w-1; + h = effects[node].h-1; + DrawRect(GR_RGB(40,255,40),x,y,x+w,y+h,vport); + }break; + case BE_MOVIE: + break; + case BE_BKG: + break; + case BE_POLY: + break; + case BE_BUTTON: + if(effects[node].w==-1){ + //we need to set up values + int handle = bm_AllocLoadFileBitmap(effects[node].button_desc.filename,0); + if(handle>BAD_BITMAP_HANDLE){ + effects[node].w = bm_w(handle,0); + effects[node].h = bm_h(handle,0); + bm_FreeBitmap(handle); + }else{ + effects[node].w = effects[node].h = 16; + } + } + int x,y,w,h; + x = effects[node].button_desc.x; + y = effects[node].button_desc.y; + w = effects[node].w-1; + h = effects[node].h-1; + DrawRect(GR_RGB(255,255,40),x,y,x+w,y+h,vport); + break; + } + } + node = effects[node].next; + } + } + + vport->unlock(); + x = rect.left + (w/2) - m_ObjectSurf.width()/2; + y = rect.top + (h/2) - m_ObjectSurf.height()/2; + + Desktop_surf->blt(x, y, &m_ObjectSurf); + + rend_EndFrame(); + + delete vport; + m_ObjectSurf.free(); + Desktop_surf->attach_to_window((unsigned)NULL); + + if(first_call) + first_call = false; +} + +void CBriefEdit::OnTimer(UINT nIDEvent) +{ + UpdateView(); + CDialog::OnTimer(nIDEvent); +} + +void CBriefEdit::OnManage() +{ + CBriefManage dlg; + dlg.DoModal(); +} diff --git a/editor/BriefEdit.h b/editor/BriefEdit.h new file mode 100644 index 00000000..a2a886be --- /dev/null +++ b/editor/BriefEdit.h @@ -0,0 +1,197 @@ +#if !defined(AFX_BRIEFEDIT_H__839B53D1_41D6_11D2_B359_006008BF0B09__INCLUDED_) +#define AFX_BRIEFEDIT_H__839B53D1_41D6_11D2_B359_006008BF0B09__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// BriefEdit.h : header file +// + +#include "pstypes.h" +#include "telcomefxstructs.h" +#include "telcom.h" +#include "gr.h" +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// CBriefEdit dialog + +#define MAX_EFFECTS_PER_SCREEN 32 + +// BriefGlobalValues +// +// struct for global variables for a telcom briefing +typedef struct{ + char title[128]; + float static_val,glitch_val; +}BriefGlobalValues; + +#define BE_NONE -1 +#define BE_TEXT 0 +#define BE_BMP 1 +#define BE_MOVIE 2 +#define BE_BKG 3 +#define BE_POLY 4 +#define BE_SND 5 +#define BE_BUTTON 6 +// tBriefEffect +// +// struct for a briefing effect +typedef struct{ + ubyte type; //type of effect (for union) + bool used; //is the effect being used + int id; //ID# used + char *text; //buffer of text + char description[128]; + int w,h;//used for bitmaps + union{ + TCTEXTDESC text_desc; + TCBMPDESC bmp_desc; + TCMOVIEDESC movie_desc; + TCBKGDESC bkg_desc; + TCPOLYDESC poly_desc; + TCSNDDESC snd_desc; + TCBUTTONDESC button_desc; + }; + int next,prev; //next/prev effect in list +}tBriefEffect; + +typedef struct{ + bool used; //is screen being used + int root_effect; //root effect to start the list + char layout[_MAX_PATH]; //layout screen to use + tBriefEffect effects[MAX_EFFECTS_PER_SCREEN]; //the effects for the screen + uint mission_mask_set,mission_mask_unset; + int next,prev; //next/prev screen in list +}tBriefScreen; + +extern int Briefing_root_screen; +extern tBriefScreen Briefing_screens[MAX_TELCOM_SCREENS]; + +/* + **************************************************************************** + * Functions to manipulate effects/screens in briefing editor * + **************************************************************************** + * +*/ + +// BriefEditInitScreens +// +// Initializes the briefing screens so they are empty +void BriefEditInitScreens(void); + +// BriefEditInitEffect +// +// Initializes an effect to empty +void BriefEditInitEffect(tBriefEffect *efx); + +// BriefEditFreeScreens +// +// Closes down all the briefing screens, freeing memory +void BriefEditFreeScreens(void); + +// BriefEditFreeEffect +// +// Frees up any memory allocated in an effect +void BriefEditFreeEffect(tBriefEffect *efx); + +// BriefEditSaveScreens +// +// Saves out the screens to a briefing file +ubyte BriefEditSaveScreens(char *filename,CComboBox *screen_combo,BriefGlobalValues *glob); + +// BriefEditLoadScreens +// +// Loads in screens from a briefing file +ubyte BriefEditLoadScreens(char *filename,CComboBox *screen_combo,CComboBox *effect_combo,BriefGlobalValues *glob); + + +#define MAX_LAYOUT_PREDEFS 10 +typedef struct{ + char filename[_MAX_PATH]; + int num_texts,num_bmps; + struct{ + int lx,rx,ty,by; + }texts[MAX_LAYOUT_PREDEFS]; + struct{ + int x,y; + }bmps[MAX_LAYOUT_PREDEFS]; +}tLayoutScreen; + +extern tLayoutScreen *PBlayouts; +extern int *PBnum_layouts; + +class CBriefEdit : public CDialog +{ +// Construction +public: + BriefGlobalValues m_GlobalValues; + tLayoutScreen *layouts; + int num_layouts; + CBriefEdit(CWnd* pParent = NULL); // standard constructor + void ParseLayoutScreenFile(char *filename); + void SetLayoutBitmap(char *filename); + bool has_changed; + // BriefEditAllocateEffect + // + // Allocates an effect (links it and all) to be edited. Returns false on error + bool BriefEditAllocateEffect(int *screen,int *eff); + // BriefEditGetCurScreenEffect + // + // Fills in the current screen and effect that is being worked on + void BriefEditGetCurScreenEffect(int *ret_screen,int *ret_effect); + +// Dialog Data + //{{AFX_DATA(CBriefEdit) + enum { IDD = IDD_BRIEF_MAIN }; + float m_fGlitch; + float m_fStatic; + CString m_sTitle; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBriefEdit) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + int layout_bmp; + void UpdateView(); + void UpdateInfo(); + void UpdateLayoutBitmap(void); + void DrawRect(ddgr_color color,int lx,int ty,int rx,int by,grViewport *vport); + + grHardwareSurface m_ObjectSurf; + + // Generated message map functions + //{{AFX_MSG(CBriefEdit) + virtual void OnOK(); + afx_msg void OnBriefEffectBitmap(); + afx_msg void OnBriefEffectButton(); + afx_msg void OnBriefEffectDel(); + afx_msg void OnBriefEffectEdit(); + afx_msg void OnBriefEffectMovie(); + afx_msg void OnBriefEffectSound(); + afx_msg void OnBriefEffectText(); + afx_msg void OnBriefScreenAdd(); + afx_msg void OnBriefScreenDel(); + afx_msg void OnBriefScreenEdit(); + virtual BOOL OnInitDialog(); + afx_msg void OnDestroy(); + afx_msg void OnSelchangeBriefScreenList(); + afx_msg void OnBriefSave(); + afx_msg void OnLoad(); + afx_msg void OnTimer(UINT nIDEvent); + afx_msg void OnManage(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BRIEFEDIT_H__839B53D1_41D6_11D2_B359_006008BF0B09__INCLUDED_) diff --git a/editor/BriefManage.cpp b/editor/BriefManage.cpp new file mode 100644 index 00000000..66293b65 --- /dev/null +++ b/editor/BriefManage.cpp @@ -0,0 +1,391 @@ +// BriefManage.cpp : implementation file +// + +#include "stdafx.h" +#include "BriefManage.h" +#include "editor.h" +#include "ddio.h" +#include "manage.h" +#include "pserror.h" +#include "pstypes.h" +#include "gamefile.h" +#include "soundpage.h" +#include "editlinedialog.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBriefManage dialog + + +CBriefManage::CBriefManage(CWnd* pParent /*=NULL*/) + : CDialog(CBriefManage::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBriefManage) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CBriefManage::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBriefManage) + DDX_Control(pDX, IDC_LIST, m_List); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CBriefManage, CDialog) + //{{AFX_MSG_MAP(CBriefManage) + ON_BN_CLICKED(IDC_ADD, OnAdd) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBriefManage message handlers +bool AddNewGameFile(char *fullpath,char *directory); +bool CheckInGamefile(char *tempbuffer,bool show_ok_confirmation); +void CBriefManage::OnAdd() +{ + if(!Network_up){ + MessageBox("You need to say YES on the data update when starting the editor"); + return; + } + + int sel = m_List.GetCurSel(); + if(sel==LB_ERR){ + MessageBox("Please select the file you want to add"); + return; + } + + char full_buffer[_MAX_PATH+100]; + m_List.GetText(sel,full_buffer); + + int page_type = -1; + char *ptr; + + //break it down + ptr = full_buffer + strlen(full_buffer); + + while( ptr>full_buffer && (*ptr)!='|') ptr--; + + if(*ptr!='|'){ + MessageBox("Internal Error"); + Int3();//get jeff; + return; + } + + *ptr = '\0'; + ptr++; + + if(page_type==-1 && strstr(ptr,"[sound]")) + page_type=PAGETYPE_SOUND; + if(page_type==-1 && strstr(ptr,"[file]")) + page_type=PAGETYPE_GAMEFILE; + + if(page_type==-1){ + MessageBox("Internal Error"); + Int3(); //get Jeff + return; + } + + if(page_type==PAGETYPE_SOUND){ + MessageBox("You must add sounds in the sound dialog"); + return; + } + + switch(page_type) + { + case PAGETYPE_GAMEFILE: + { + char filename[255]; + char real_filename[_MAX_PATH]; + + strcpy(filename,full_buffer); + + // Get the filename of the representing image + CString filter = ""; + + if (!OpenFileDialog(this, (LPCTSTR)filter, filename, Current_files_dir, sizeof(Current_files_dir))) + return; + + char directory[32],ext[32]; + bool know_dir = false; + + ddio_SplitPath(filename,NULL,real_filename,ext); + strcat(real_filename,ext); + + if(!know_dir && !stricmp(ext,".ogf")){ + know_dir = true; + strcpy(directory,"graphics"); + } + + if(!know_dir && !stricmp(ext,".tga")){ + know_dir = true; + strcpy(directory,"graphics"); + } + + if(!know_dir && !stricmp(ext,".pcx")){ + know_dir = true; + strcpy(directory,"graphics"); + } + + if(!know_dir && !stricmp(ext,".oof")){ + know_dir = true; + strcpy(directory,"models"); + } + + if(!know_dir){ + CEditLineDialog dlg("What directory does this belong in?","Directory", "graphics", false, this); + if(dlg.DoModal()!=IDOK) + return; + + strcpy(directory,dlg.GetText()); + + bool is_ok = false; + + if(!is_ok && !stricmp(directory,"briefings") ) + is_ok = true; + + if(!is_ok && !stricmp(directory,"graphics") ) + is_ok = true; + + if(!is_ok && !stricmp(directory,"levels") ) + is_ok = true; + + if(!is_ok && !stricmp(directory,"misc") ) + is_ok = true; + + if(!is_ok && !stricmp(directory,"models") ) + is_ok = true; + + if(!is_ok && !stricmp(directory,"music") ) + is_ok = true; + + if(!is_ok && !stricmp(directory,"scripts") ) + is_ok = true; + + if(!is_ok && !stricmp(directory,"sounds") ) + is_ok = true; + + if(!is_ok){ + MessageBox("Invalid directory"); + return; + } + } + + if(!AddNewGameFile(filename,directory)){ + char buffer[_MAX_PATH*2]; + sprintf(buffer,"Unable to add:\r\n%s\r\nto %s",filename,directory); + MessageBox(buffer); + return; + } + + //auto checkin + if (!mng_MakeLocker()){ + return; + } + + if(!CheckInGamefile(real_filename,true)){ + MessageBox("Unable to auto-checkin"); + } + + mng_EraseLocker(); + }break; + } + + UpdateDialog(); +} + +BOOL CBriefManage::OnInitDialog() +{ + CDialog::OnInitDialog(); + + UpdateDialog(); + + return TRUE; +} + +void CBriefManage::AddString(char *filename,int pagetype) +{ + char buffer[_MAX_PATH+100]; + char real_filename[_MAX_PATH]; + char page_type[100]; + char *pagename = filename; + + switch(pagetype) + { + case PAGETYPE_SOUND: + { + //look for the page in the manage system + bool found; + + found = false; + + mngs_sound_page page; + + if(mng_FindSpecificSoundPage(filename,&page )>0) + { + found = true; + } + + if(!found){ + //ok there wasn't one in the gamefiles make sure there isn't a tracklocked + if(mng_FindTrackLock(filename,PAGETYPE_SOUND)!=-1){ + //there isn't one in the track lock...this is our first compile! + found = true; + } + } + + if(found){ + //we already have this in the manage system + return; + } + + + strcpy(page_type,"[sound]"); + }break; + case PAGETYPE_GAMEFILE: + { + //look for the page in the manage system + bool found; + int i; + + char ext[32]; + ddio_SplitPath(filename,NULL,real_filename,ext); + strcat(real_filename,ext); + pagename = real_filename; + + found = false; + for (i=0;iused); + + if(screen->layout[0]!='\0'){ + //add the layout screen + AddString(screen->layout); + } + + //go through all the effects for this screen + curr_effect = screen->root_effect; + while(curr_effect!=-1) + { + effect = &screen->effects[curr_effect]; + ASSERT(effect->used); + + switch(effect->type){ + case BE_MOVIE: + case BE_TEXT: + case BE_BKG: + break; //no files in here + + case BE_BMP: + if(*effect->bmp_desc.filename) + { + AddString(effect->bmp_desc.filename); + } + break; + + case BE_POLY: + if(*effect->poly_desc.polyname) + { + AddString(effect->poly_desc.polyname); + } + break; + case BE_SND: + if(*effect->snd_desc.filename) + { + AddString(effect->snd_desc.filename,PAGETYPE_SOUND); + } + break; + case BE_BUTTON: + if(*effect->button_desc.filename) + { + AddString(effect->button_desc.filename); + } + + if(*effect->button_desc.filename_focus) + { + AddString(effect->button_desc.filename_focus); + } + + if(*effect->button_desc.flash_filename) + { + AddString(effect->button_desc.flash_filename); + } + + if(*effect->button_desc.flash_filename_focus) + { + AddString(effect->button_desc.flash_filename_focus); + } + + break; + default: + break; + } + + + curr_effect = effect->next; + } + + curr_screen = screen->next; + } + + m_List.SetCurSel(0); +} \ No newline at end of file diff --git a/editor/BriefManage.h b/editor/BriefManage.h new file mode 100644 index 00000000..27bf35b1 --- /dev/null +++ b/editor/BriefManage.h @@ -0,0 +1,53 @@ +#if !defined(AFX_BRIEFMANAGE_H__76AADF40_C377_11D2_AB2B_006008BF0B09__INCLUDED_) +#define AFX_BRIEFMANAGE_H__76AADF40_C377_11D2_AB2B_006008BF0B09__INCLUDED_ + + +#include "BriefEdit.h" + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// BriefManage.h : header file +// + +#include "manage.h" +///////////////////////////////////////////////////////////////////////////// +// CBriefManage dialog + +class CBriefManage : public CDialog +{ +// Construction +public: + CBriefManage(CWnd* pParent = NULL); // standard constructor + void UpdateDialog(void); + void AddString(char *filename,int pagetype=PAGETYPE_GAMEFILE); + +// Dialog Data + //{{AFX_DATA(CBriefManage) + enum { IDD = IDD_BRIEF_MANAGE }; + CListBox m_List; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBriefManage) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CBriefManage) + afx_msg void OnAdd(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BRIEFMANAGE_H__76AADF40_C377_11D2_AB2B_006008BF0B09__INCLUDED_) diff --git a/editor/BriefMissionFlagsDlg.cpp b/editor/BriefMissionFlagsDlg.cpp new file mode 100644 index 00000000..d4b93c1b --- /dev/null +++ b/editor/BriefMissionFlagsDlg.cpp @@ -0,0 +1,265 @@ +// BriefMissionFlagsDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "BriefMissionFlagsDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBriefMissionFlagsDlg dialog + + +CBriefMissionFlagsDlg::CBriefMissionFlagsDlg(uint setflags,uint unsetflags,CWnd* pParent /*=NULL*/) + : CDialog(CBriefMissionFlagsDlg::IDD, pParent) +{ + m_Set = setflags; + m_UnSet = unsetflags; + + //{{AFX_DATA_INIT(CBriefMissionFlagsDlg) + m_1 = 0; + m_10 = 0; + m_11 = 0; + m_12 = 0; + m_13 = 0; + m_14 = 0; + m_15 = 0; + m_16 = 0; + m_17 = 0; + m_18 = 0; + m_19 = 0; + m_2 = 0; + m_20 = 0; + m_21 = 0; + m_22 = 0; + m_23 = 0; + m_24 = 0; + m_25 = 0; + m_26 = 0; + m_27 = 0; + m_28 = 0; + m_29 = 0; + m_3 = 0; + m_30 = 0; + m_31 = 0; + m_32 = 0; + m_4 = 0; + m_5 = 0; + m_6 = 0; + m_7 = 0; + m_9 = 0; + m_8 = 0; + //}}AFX_DATA_INIT +} + + +void CBriefMissionFlagsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBriefMissionFlagsDlg) + DDX_Radio(pDX, IDC_D_FLAG1, m_1); + DDX_Radio(pDX, IDC_D_FLAG10, m_10); + DDX_Radio(pDX, IDC_D_FLAG11, m_11); + DDX_Radio(pDX, IDC_D_FLAG12, m_12); + DDX_Radio(pDX, IDC_D_FLAG13, m_13); + DDX_Radio(pDX, IDC_D_FLAG14, m_14); + DDX_Radio(pDX, IDC_D_FLAG15, m_15); + DDX_Radio(pDX, IDC_D_FLAG16, m_16); + DDX_Radio(pDX, IDC_D_FLAG17, m_17); + DDX_Radio(pDX, IDC_D_FLAG18, m_18); + DDX_Radio(pDX, IDC_D_FLAG19, m_19); + DDX_Radio(pDX, IDC_D_FLAG2, m_2); + DDX_Radio(pDX, IDC_D_FLAG20, m_20); + DDX_Radio(pDX, IDC_D_FLAG21, m_21); + DDX_Radio(pDX, IDC_D_FLAG22, m_22); + DDX_Radio(pDX, IDC_D_FLAG23, m_23); + DDX_Radio(pDX, IDC_D_FLAG24, m_24); + DDX_Radio(pDX, IDC_D_FLAG25, m_25); + DDX_Radio(pDX, IDC_D_FLAG26, m_26); + DDX_Radio(pDX, IDC_D_FLAG27, m_27); + DDX_Radio(pDX, IDC_D_FLAG28, m_28); + DDX_Radio(pDX, IDC_D_FLAG29, m_29); + DDX_Radio(pDX, IDC_D_FLAG3, m_3); + DDX_Radio(pDX, IDC_D_FLAG30, m_30); + DDX_Radio(pDX, IDC_D_FLAG31, m_31); + DDX_Radio(pDX, IDC_D_FLAG32, m_32); + DDX_Radio(pDX, IDC_D_FLAG4, m_4); + DDX_Radio(pDX, IDC_D_FLAG5, m_5); + DDX_Radio(pDX, IDC_D_FLAG6, m_6); + DDX_Radio(pDX, IDC_D_FLAG7, m_7); + DDX_Radio(pDX, IDC_D_FLAG9, m_9); + DDX_Radio(pDX, IDC_D_FLAG8, m_8); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CBriefMissionFlagsDlg, CDialog) + //{{AFX_MSG_MAP(CBriefMissionFlagsDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBriefMissionFlagsDlg message handlers + +void CBriefMissionFlagsDlg::OnOK() +{ + UpdateData(true); + + m_Set = m_UnSet = 0; + + uint bit = 0x01; + int i,value; + + for(i=0;i<32;i++){ + + switch(i){ + case 0:value = m_1;break; + case 1:value = m_2;break; + case 2:value = m_3;break; + case 3:value = m_4;break; + case 4:value = m_5;break; + case 5:value = m_6;break; + case 6:value = m_7;break; + case 7:value = m_8;break; + case 8:value = m_9;break; + case 9:value = m_10;break; + case 10:value= m_11;break; + case 11:value= m_12;break; + case 12:value= m_13;break; + case 13:value= m_14;break; + case 14:value= m_15;break; + case 15:value= m_16;break; + case 16:value= m_17;break; + case 17:value= m_18;break; + case 18:value= m_19;break; + case 19:value= m_20;break; + case 20:value= m_21;break; + case 21:value= m_22;break; + case 22:value= m_23;break; + case 23:value= m_24;break; + case 24:value= m_25;break; + case 25:value= m_26;break; + case 26:value= m_27;break; + case 27:value= m_28;break; + case 28:value= m_29;break; + case 29:value= m_30;break; + case 30:value= m_31;break; + case 31:value= m_32;break; + }; + + switch(value){ + case 0:break; + case 1: m_Set |= bit; break; + case 2: m_UnSet |= bit; break; + }; + + bit = bit << 1; + } + + CDialog::OnOK(); +} + +BOOL CBriefMissionFlagsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + uint bit = 0x01; + int i; + + //First go through the set bits + for(i=0;i<32;i++){ + if(m_Set&bit){ + //turn on + switch(i){ + case 0: m_1 = 1; break; + case 1: m_2 = 1; break; + case 2: m_3 = 1; break; + case 3: m_4 = 1; break; + case 4: m_5 = 1; break; + case 5: m_6 = 1; break; + case 6: m_7 = 1; break; + case 7: m_8 = 1; break; + case 8: m_9 = 1; break; + case 9: m_10 = 1; break; + case 10: m_11 = 1; break; + case 11: m_12 = 1; break; + case 12: m_13 = 1; break; + case 13: m_14 = 1; break; + case 14: m_15 = 1; break; + case 15: m_16 = 1; break; + case 16: m_17 = 1; break; + case 17: m_18 = 1; break; + case 18: m_19 = 1; break; + case 19: m_20 = 1; break; + case 20: m_21 = 1; break; + case 21: m_22 = 1; break; + case 22: m_23 = 1; break; + case 23: m_24 = 1; break; + case 24: m_25 = 1; break; + case 25: m_26 = 1; break; + case 26: m_27 = 1; break; + case 27: m_28 = 1; break; + case 28: m_29 = 1; break; + case 29: m_30 = 1; break; + case 30: m_31 = 1; break; + case 31: m_32 = 1; break; + }; + + } + bit = bit << 1; + } + + bit = 0x01; + //now do the turned off bits + for(i=0;i<32;i++){ + if(m_UnSet&bit){ + //turn on + switch(i){ + case 0: m_1 = 2; break; + case 1: m_2 = 2; break; + case 2: m_3 = 2; break; + case 3: m_4 = 2; break; + case 4: m_5 = 2; break; + case 5: m_6 = 2; break; + case 6: m_7 = 2; break; + case 7: m_8 = 2; break; + case 8: m_9 = 2; break; + case 9: m_10 = 2; break; + case 10: m_11 = 2; break; + case 11: m_12 = 2; break; + case 12: m_13 = 2; break; + case 13: m_14 = 2; break; + case 14: m_15 = 2; break; + case 15: m_16 = 2; break; + case 16: m_17 = 2; break; + case 17: m_18 = 2; break; + case 18: m_19 = 2; break; + case 19: m_20 = 2; break; + case 20: m_21 = 2; break; + case 21: m_22 = 2; break; + case 22: m_23 = 2; break; + case 23: m_24 = 2; break; + case 24: m_25 = 2; break; + case 25: m_26 = 2; break; + case 26: m_27 = 2; break; + case 27: m_28 = 2; break; + case 28: m_29 = 2; break; + case 29: m_30 = 2; break; + case 30: m_31 = 2; break; + case 31: m_32 = 2; break; + }; + + } + bit = bit << 1; + } + + UpdateData(false); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/editor/BriefMissionFlagsDlg.h b/editor/BriefMissionFlagsDlg.h new file mode 100644 index 00000000..ca1c701d --- /dev/null +++ b/editor/BriefMissionFlagsDlg.h @@ -0,0 +1,81 @@ +#if !defined(AFX_BRIEFMISSIONFLAGSDLG_H__C79F9EC0_A3E9_11D2_AB2B_006008BF0B09__INCLUDED_) +#define AFX_BRIEFMISSIONFLAGSDLG_H__C79F9EC0_A3E9_11D2_AB2B_006008BF0B09__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// BriefMissionFlagsDlg.h : header file +// +#include "pstypes.h" +///////////////////////////////////////////////////////////////////////////// +// CBriefMissionFlagsDlg dialog + +class CBriefMissionFlagsDlg : public CDialog +{ +// Construction +public: + CBriefMissionFlagsDlg(uint setflags,uint unsetflags,CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CBriefMissionFlagsDlg) + enum { IDD = IDD_BRIEFMISSIONFLAGS }; + int m_1; + int m_10; + int m_11; + int m_12; + int m_13; + int m_14; + int m_15; + int m_16; + int m_17; + int m_18; + int m_19; + int m_2; + int m_20; + int m_21; + int m_22; + int m_23; + int m_24; + int m_25; + int m_26; + int m_27; + int m_28; + int m_29; + int m_3; + int m_30; + int m_31; + int m_32; + int m_4; + int m_5; + int m_6; + int m_7; + int m_9; + int m_8; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBriefMissionFlagsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +public: + uint m_Set,m_UnSet; + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CBriefMissionFlagsDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BRIEFMISSIONFLAGSDLG_H__C79F9EC0_A3E9_11D2_AB2B_006008BF0B09__INCLUDED_) diff --git a/editor/BriefMovieEdit.cpp b/editor/BriefMovieEdit.cpp new file mode 100644 index 00000000..1f57554c --- /dev/null +++ b/editor/BriefMovieEdit.cpp @@ -0,0 +1,156 @@ +// BriefMovieEdit.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "BriefMovieEdit.h" +#include "manage.h" +#include "BriefMissionFlagsDlg.h" +#include "ddio.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBriefMovieEdit dialog + + +CBriefMovieEdit::CBriefMovieEdit(LPTCMOVIEDESC d,CWnd* pParent /*=NULL*/) + : CDialog(CBriefMovieEdit::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBriefMovieEdit) + m_sFilename = _T(""); + m_fFPS = 0.0f; + m_bLooping = FALSE; + m_fStartTime = 0.0f; + m_iX = 0; + m_iY = 0; + m_sDesc = _T(""); + //}}AFX_DATA_INIT + + memset(&desc,0,sizeof(TCMOVIEDESC)); + + //set defaults + desc.fps = 20.0f; + desc.mission_mask_set = 0; + desc.mission_mask_unset = 0; + + + if(d){ + //get given values) + desc.caps = d->caps; + + if(d->caps&TCMD_XY){ + desc.x = d->x; + desc.y = d->y; + } + if(d->caps&TCMD_LOOPING) + desc.looping = d->looping; + if(d->caps&TCMD_WAITTIME) + desc.waittime = d->waittime; + if(d->caps&TCMD_FPS) + desc.fps = d->fps; + + desc.mission_mask_set = d->mission_mask_set; + desc.mission_mask_unset = d->mission_mask_unset; + + strcpy(desc.filename,d->filename); + } + + //fill in with whats valid + m_sFilename = desc.filename; + m_fFPS = desc.fps; + m_bLooping = desc.looping; + m_fStartTime = desc.waittime; + m_iX = desc.x; + m_iY = desc.y; + +} + + +void CBriefMovieEdit::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBriefMovieEdit) + DDX_Text(pDX, IDC_BRIEF_M_FILENAME, m_sFilename); + DDX_Text(pDX, IDC_BRIEF_M_FPS, m_fFPS); + DDV_MinMaxFloat(pDX, m_fFPS, 0.f, 100.f); + DDX_Check(pDX, IDC_BRIEF_M_LOOPING, m_bLooping); + DDX_Text(pDX, IDC_BRIEF_M_STARTTIME, m_fStartTime); + DDV_MinMaxFloat(pDX, m_fStartTime, 0.f, 99999.f); + DDX_Text(pDX, IDC_BRIEF_M_X, m_iX); + DDV_MinMaxInt(pDX, m_iX, 0, 639); + DDX_Text(pDX, IDC_BRIEF_M_Y, m_iY); + DDV_MinMaxInt(pDX, m_iY, 0, 479); + DDX_Text(pDX, IDC_BRIEF_M_DESC, m_sDesc); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CBriefMovieEdit, CDialog) + //{{AFX_MSG_MAP(CBriefMovieEdit) + ON_BN_CLICKED(IDC_BRIEF_M_CHOOSE, OnBriefMChoose) + ON_BN_CLICKED(IDC_MISSIONFLAGS, OnMissionflags) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBriefMovieEdit message handlers + +void CBriefMovieEdit::OnBriefMChoose() +{ + UpdateData(true); + char szFilter[] = "Outrage Movie Files (*.mve)|*.mve||"; + CFileDialog dlg(true,NULL,NULL,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,szFilter); + + if(dlg.DoModal()==IDOK){ + //handle + m_sFilename = dlg.GetFileName(); + UpdateData(false); + } +} + +void CBriefMovieEdit::OnOK() +{ + UpdateData(true); + + char path[_MAX_PATH]; + ddio_MakePath(path,LocalD3Dir,"Movies",m_sFilename.GetBuffer(1),NULL); + + if(!cfexist(path)){ + MessageBox("Invalid Filename","Error"); + return; + } + + desc.caps = TCMD_XY|TCMD_LOOPING|TCMD_WAITTIME|TCMD_FPS; + strcpy(desc.filename,m_sFilename.GetBuffer(0)); + desc.fps = m_fFPS; + desc.looping = (bool)(m_bLooping!=0); + desc.waittime = m_fStartTime; + desc.x = m_iX; + desc.y = m_iY; + + CDialog::OnOK(); +} + +BOOL CBriefMovieEdit::OnInitDialog() +{ + CDialog::OnInitDialog(); + + UpdateData(false); + + return TRUE; +} + +void CBriefMovieEdit::OnMissionflags() +{ + CBriefMissionFlagsDlg dlg(desc.mission_mask_set,desc.mission_mask_unset); + + if(dlg.DoModal()){ + desc.mission_mask_set = dlg.m_Set; + desc.mission_mask_unset = dlg.m_UnSet; + } +} diff --git a/editor/BriefMovieEdit.h b/editor/BriefMovieEdit.h new file mode 100644 index 00000000..27f92147 --- /dev/null +++ b/editor/BriefMovieEdit.h @@ -0,0 +1,60 @@ +#if !defined(AFX_BRIEFMOVIEEDIT_H__01F120A3_427B_11D2_B359_006008BF0B09__INCLUDED_) +#define AFX_BRIEFMOVIEEDIT_H__01F120A3_427B_11D2_B359_006008BF0B09__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// BriefMovieEdit.h : header file +// + +#include "telcomefxstructs.h" +#include "TelcomEffects.h" + +///////////////////////////////////////////////////////////////////////////// +// CBriefMovieEdit dialog + +class CBriefMovieEdit : public CDialog +{ +// Construction +public: + CBriefMovieEdit(LPTCMOVIEDESC desc=NULL,CWnd* pParent = NULL); // standard constructor + TCMOVIEDESC desc; + + +// Dialog Data + //{{AFX_DATA(CBriefMovieEdit) + enum { IDD = IDD_BRIEF_ADDMOVIE }; + CString m_sFilename; + float m_fFPS; + BOOL m_bLooping; + float m_fStartTime; + int m_iX; + int m_iY; + CString m_sDesc; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBriefMovieEdit) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CBriefMovieEdit) + afx_msg void OnBriefMChoose(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnMissionflags(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BRIEFMOVIEEDIT_H__01F120A3_427B_11D2_B359_006008BF0B09__INCLUDED_) diff --git a/editor/BriefScreenEdit.cpp b/editor/BriefScreenEdit.cpp new file mode 100644 index 00000000..b441455d --- /dev/null +++ b/editor/BriefScreenEdit.cpp @@ -0,0 +1,189 @@ +// BriefScreenEdit.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "BriefScreenEdit.h" +#include "BriefEdit.h" +#include "BriefMissionFlagsDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBriefScreenEdit dialog + + +CBriefScreenEdit::CBriefScreenEdit(int screen_idx,CWnd* pParent /*=NULL*/) + : CDialog(CBriefScreenEdit::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBriefScreenEdit) + m_sDesc = _T(""); + //}}AFX_DATA_INIT + m_Screen = screen_idx; + bm_handle = -1; + m_Set = m_UnSet = 0; +} + + +void CBriefScreenEdit::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBriefScreenEdit) + DDX_Text(pDX, IDC_BRIEF_ADDS_DESC, m_sDesc); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CBriefScreenEdit, CDialog) + //{{AFX_MSG_MAP(CBriefScreenEdit) + ON_WM_TIMER() + ON_CBN_SELCHANGE(IDC_BRIEF_ADDS_LAYOUT_LIST, OnSelchangeBriefAddsLayoutList) + ON_BN_CLICKED(IDC_MISSIONFLAGS, OnMissionflags) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBriefScreenEdit message handlers + +void CBriefScreenEdit::OnOK() +{ + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_ADDS_LAYOUT_LIST); + int sel = combo->GetCurSel(); + if(sel>0){ + combo->GetLBText(sel,layout_str); + }else{ + layout_str = ""; + } + + if(bm_handle>BAD_BITMAP_HANDLE) + bm_FreeBitmap(bm_handle); + + CDialog::OnOK(); +} + +BOOL CBriefScreenEdit::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_ADDS_LAYOUT_LIST); + + //Start the timer + CWnd::SetTimer(1,50,NULL); + + combo->AddString(""); + int sel = 0; + + for(int i=0;i<(*PBnum_layouts);i++){ + combo->AddString(PBlayouts[i].filename); + if(m_Screen!=-1){ + if(!stricmp(Briefing_screens[m_Screen].layout,PBlayouts[i].filename)) + sel = i+1; + } + } + + if(m_Screen!=-1){ + m_Set = Briefing_screens[m_Screen].mission_mask_set; + m_UnSet = Briefing_screens[m_Screen].mission_mask_unset; + } + + combo->SetCurSel(sel); + + return TRUE; +} + +void CBriefScreenEdit::UpdateView(void) +{ + CWnd *objwnd; + RECT rect; + int x,y,w,h; + + objwnd = GetDlgItem(IDC_BRIEF_ADDS_PICTURE); + objwnd->GetWindowRect(&rect); + ScreenToClient(&rect); + + int bmw,bmh; + + Desktop_surf->attach_to_window((unsigned)m_hWnd); + + w=rect.right-rect.left; + h=rect.bottom-rect.top; + + bmw = w; + bmh = h; + + static bool first_call = true; + + if(first_call) + Desktop_surf->clear(rect.left,rect.top,w,h); + + m_ObjectSurf.create(bmw, bmh, BPP_16); + + if(bm_handle>BAD_BITMAP_HANDLE){ + m_ObjectSurf.load(bm_handle); + }else + Desktop_surf->clear(rect.left,rect.top,w,h); + + x = rect.left + (w/2) - m_ObjectSurf.width()/2; + y = rect.top + (h/2) - m_ObjectSurf.height()/2; + + Desktop_surf->blt(x, y, &m_ObjectSurf); + + m_ObjectSurf.free(); + Desktop_surf->attach_to_window((unsigned)NULL); + + if(first_call) + first_call = false; +} + +void CBriefScreenEdit::OnTimer(UINT nIDEvent) +{ + UpdateView(); + CDialog::OnTimer(nIDEvent); +} + +void CBriefScreenEdit::OnSelchangeBriefAddsLayoutList() +{ + if(bm_handle>BAD_BITMAP_HANDLE){ + bm_FreeBitmap(bm_handle); + bm_handle = -1; + } + + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_ADDS_LAYOUT_LIST); + int sel = combo->GetCurSel(); + if(sel>0){ + bm_handle = bm_AllocLoadFileBitmap(PBlayouts[sel-1].filename,0); + } + + CWnd *objwnd; + RECT rect; + int w,h; + + objwnd = GetDlgItem(IDC_BRIEF_ADDS_PICTURE); + objwnd->GetWindowRect(&rect); + w=rect.right-rect.left; + h=rect.bottom-rect.top; + + int temp = bm_AllocBitmap(w,h,0); + if(temp>BAD_BITMAP_HANDLE){ + bm_ClearBitmap(temp); + if(bm_handle>BAD_BITMAP_HANDLE){ + bm_ScaleBitmapToBitmap (temp,bm_handle); + } + bm_FreeBitmap(bm_handle); + bm_handle = temp; + } +} + +void CBriefScreenEdit::OnMissionflags() +{ + CBriefMissionFlagsDlg dlg(m_Set,m_UnSet); + + if(dlg.DoModal()){ + m_Set = dlg.m_Set; + m_UnSet = dlg.m_UnSet; + } +} diff --git a/editor/BriefScreenEdit.h b/editor/BriefScreenEdit.h new file mode 100644 index 00000000..bd7b891a --- /dev/null +++ b/editor/BriefScreenEdit.h @@ -0,0 +1,57 @@ +#if !defined(AFX_BRIEFSCREENEDIT_H__01F120A4_427B_11D2_B359_006008BF0B09__INCLUDED_) +#define AFX_BRIEFSCREENEDIT_H__01F120A4_427B_11D2_B359_006008BF0B09__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// BriefScreenEdit.h : header file +// +#include "gr.h" +#include "pstypes.h" +///////////////////////////////////////////////////////////////////////////// +// CBriefScreenEdit dialog + +class CBriefScreenEdit : public CDialog +{ +// Construction +public: + CBriefScreenEdit(int screen_idx=-1,CWnd* pParent = NULL); // standard constructor + CString layout_str; + void UpdateView(void); + int m_Screen; + int bm_handle; + uint m_Set,m_UnSet; + grHardwareSurface m_ObjectSurf; + +// Dialog Data + //{{AFX_DATA(CBriefScreenEdit) + enum { IDD = IDD_BRIEF_ADDSCREEN }; + CString m_sDesc; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBriefScreenEdit) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CBriefScreenEdit) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnTimer(UINT nIDEvent); + afx_msg void OnSelchangeBriefAddsLayoutList(); + afx_msg void OnMissionflags(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BRIEFSCREENEDIT_H__01F120A4_427B_11D2_B359_006008BF0B09__INCLUDED_) diff --git a/editor/BriefSoundEdit.cpp b/editor/BriefSoundEdit.cpp new file mode 100644 index 00000000..bbfed6a4 --- /dev/null +++ b/editor/BriefSoundEdit.cpp @@ -0,0 +1,129 @@ +// BriefSoundEdit.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "BriefSoundEdit.h" +#include "BriefMissionFlagsDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBriefSoundEdit dialog + + +CBriefSoundEdit::CBriefSoundEdit(LPTCSNDDESC d,CWnd* pParent /*=NULL*/) + : CDialog(CBriefSoundEdit::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBriefSoundEdit) + m_sFilename = _T(""); + m_bPlayOnce = FALSE; + m_fStartTime = 0.0f; + m_sDesc = _T(""); + //}}AFX_DATA_INIT + + memset(&desc,0,sizeof(TCSNDDESC)); + + //Set defaults + desc.waittime = 0; + desc.once = false; + desc.mission_mask_set = 0; + desc.mission_mask_unset = 0; + + + if(d){ + //fill in values + strcpy(desc.filename,d->filename); + if(d->caps&TCSD_WAITTIME) + desc.waittime = d->waittime; + if(d->caps&TCSD_ONCE) + desc.once = d->once; + + desc.caps = d->caps; + desc.type = d->type; + desc.mission_mask_set = d->mission_mask_set; + desc.mission_mask_unset = d->mission_mask_unset; + } + + //Setup Window dialog + m_sFilename = desc.filename; + m_bPlayOnce = desc.once; + m_fStartTime = desc.waittime; +} + + +void CBriefSoundEdit::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBriefSoundEdit) + DDX_Text(pDX, IDC_BRIEF_S_FILENAME, m_sFilename); + DDX_Check(pDX, IDC_BRIEF_S_PLAYONCE, m_bPlayOnce); + DDX_Text(pDX, IDC_BRIEF_S_STARTTIME, m_fStartTime); + DDV_MinMaxFloat(pDX, m_fStartTime, 0.f, 99999.f); + DDX_Text(pDX, IDC_BRIEF_S_DESC, m_sDesc); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CBriefSoundEdit, CDialog) + //{{AFX_MSG_MAP(CBriefSoundEdit) + ON_BN_CLICKED(IDC_BRIEF_S_CHOOSE, OnBriefSChoose) + ON_BN_CLICKED(IDC_MISSIONFLAGS, OnMissionflags) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBriefSoundEdit message handlers + +void CBriefSoundEdit::OnBriefSChoose() +{ + UpdateData(true); + char szFilter[] = "WAV File (*.wav)|*.wav||"; + CFileDialog dlg(true,NULL,NULL,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,szFilter); + + if(dlg.DoModal()==IDOK){ + //handle + m_sFilename = dlg.GetFileName(); + UpdateData(false); + } +} + +void CBriefSoundEdit::OnOK() +{ + if(!cfexist(m_sFilename.GetBuffer(1))){ + MessageBox("Invalid Filename, Please Enter A Valid Filename","Error"); + return; + } + + UpdateData(true); + + desc.caps = TCSD_WAITTIME|TCSD_ONCE; + strcpy(desc.filename,m_sFilename.GetBuffer(0)); + desc.once = (bool)(m_bPlayOnce!=0); + desc.waittime = m_fStartTime; + + CDialog::OnOK(); +} + +BOOL CBriefSoundEdit::OnInitDialog() +{ + CDialog::OnInitDialog(); + + UpdateData(false); + + return TRUE; +} + +void CBriefSoundEdit::OnMissionflags() +{ + CBriefMissionFlagsDlg dlg(desc.mission_mask_set,desc.mission_mask_unset); + + if(dlg.DoModal()){ + desc.mission_mask_set = dlg.m_Set; + desc.mission_mask_unset = dlg.m_UnSet; + } +} diff --git a/editor/BriefSoundEdit.h b/editor/BriefSoundEdit.h new file mode 100644 index 00000000..ddb3f3e5 --- /dev/null +++ b/editor/BriefSoundEdit.h @@ -0,0 +1,55 @@ +#if !defined(AFX_BRIEFSOUNDEDIT_H__01F120A5_427B_11D2_B359_006008BF0B09__INCLUDED_) +#define AFX_BRIEFSOUNDEDIT_H__01F120A5_427B_11D2_B359_006008BF0B09__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// BriefSoundEdit.h : header file +// +#include "telcomefxstructs.h" +#include "TelComEffects.h" + +///////////////////////////////////////////////////////////////////////////// +// CBriefSoundEdit dialog + +class CBriefSoundEdit : public CDialog +{ +// Construction +public: + CBriefSoundEdit(LPTCSNDDESC desc=NULL,CWnd* pParent = NULL); // standard constructor + TCSNDDESC desc; + +// Dialog Data + //{{AFX_DATA(CBriefSoundEdit) + enum { IDD = IDD_BRIEF_ADDSOUND }; + CString m_sFilename; + BOOL m_bPlayOnce; + float m_fStartTime; + CString m_sDesc; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBriefSoundEdit) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CBriefSoundEdit) + afx_msg void OnBriefSChoose(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnMissionflags(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BRIEFSOUNDEDIT_H__01F120A5_427B_11D2_B359_006008BF0B09__INCLUDED_) diff --git a/editor/BriefTextEdit.cpp b/editor/BriefTextEdit.cpp new file mode 100644 index 00000000..21eb1c24 --- /dev/null +++ b/editor/BriefTextEdit.cpp @@ -0,0 +1,372 @@ +// BriefTextEdit.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "BriefTextEdit.h" +#include "BriefEdit.h" +#include "BriefMissionFlagsDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBriefTextEdit dialog + + +CBriefTextEdit::CBriefTextEdit(int curr_screen,LPTCTEXTDESC d,char *text_buffer,int id,CWnd* pParent /*=NULL*/) + : CDialog(CBriefTextEdit::IDD, pParent) +{ + m_Screen = curr_screen; + //{{AFX_DATA_INIT(CBriefTextEdit) + m_iID = 0; + m_iBY = 0; + m_iRX = 0; + m_fSpeed = 0.0f; + m_fStartTime = 0.0f; + m_iTY = 0; + m_iLX = 0; + m_iEffectType = -1; + m_sDesc = _T(""); + m_iBlue = 0; + m_iGreen = 0; + m_iRed = 0; + m_TabStop = FALSE; + //}}AFX_DATA_INIT + + memset(&desc,0,sizeof(TCTEXTDESC)); + + //set defaults + desc.type = TC_TEXT_STATIC; + desc.font = BRIEF_FONT_INDEX; + desc.color = GR_GREEN; + desc.speed = 1.0f; + desc.looping = false; + desc.waittime = 0; + desc.textbox.left = desc.textbox.top = 0; + desc.textbox.right = 639; + desc.textbox.bottom = 479; + desc.mission_mask_set = 0; + desc.mission_mask_unset = 0; + + m_TabStop = false; + if(d){ + desc.caps = d->caps; + desc.flags = d->flags; + desc.type = d->type; + //fill in values + if(d->caps&TCTD_FONT) + desc.font = d->font; + if(d->caps&TCTD_COLOR) + desc.color = d->color; + if(d->caps&TCTD_SPEED) + desc.speed = d->speed; + if(d->caps&TCTD_LOOPING) + desc.looping = d->looping; + if(d->caps&TCTD_TEXTBOX) + memcpy(&desc.textbox,&d->textbox,sizeof(tc_text)); + if(d->caps&TCTD_WAITTIME) + desc.waittime = d->waittime; + if(d->caps&TCTD_TABSTOP) + m_TabStop = true; + + desc.mission_mask_set = d->mission_mask_set; + desc.mission_mask_unset = d->mission_mask_unset; + } + + if(text_buffer) + m_Text = text_buffer; + else + m_Text = ""; + + //Set window dialog information + m_iID = id; + m_iBY = desc.textbox.bottom; + m_iRX = desc.textbox.right; + m_iTY = desc.textbox.top; + m_iLX = desc.textbox.left; + m_fSpeed = desc.speed; + m_fStartTime = desc.waittime; + m_iRed = GR_COLOR_RED(desc.color); + m_iGreen = GR_COLOR_GREEN(desc.color); + m_iBlue = GR_COLOR_BLUE(desc.color); + + switch(desc.type){ + case TC_TEXT_STATIC: + m_iEffectType = 0; + break; + case TC_TEXT_SCROLL: + switch(desc.flags){ + case TC_TEXTF_L2R: + m_iEffectType = 4; + break; + case TC_TEXTF_R2L: + m_iEffectType = 5; + break; + case TC_TEXTF_T2B: + m_iEffectType = 6; + break; + case TC_TEXTF_B2T: + m_iEffectType = 7; + break; + default: + m_iEffectType = 4; + break; + } + break; + case TC_TEXT_FADE: + switch(desc.flags){ + case TC_TEXTF_IN: + m_iEffectType = 2; + break; + case TC_TEXTF_OUT: + m_iEffectType = 3; + break; + default: + m_iEffectType = 2; + break; + } + break; + case TC_TEXT_FLASH: + m_iEffectType = 1; + break; + default: + m_iEffectType = 0; + } +} + + +void CBriefTextEdit::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBriefTextEdit) + DDX_Text(pDX, IDC_BRIEF_T_ID, m_iID); + DDX_Text(pDX, IDC_BRIEF_T_LR_Y, m_iBY); + DDV_MinMaxInt(pDX, m_iBY, 0, 479); + DDX_Text(pDX, IDC_BRIEF_T_LR_X, m_iRX); + DDV_MinMaxInt(pDX, m_iRX, 0, 639); + DDX_Text(pDX, IDC_BRIEF_T_SPEED, m_fSpeed); + DDV_MinMaxFloat(pDX, m_fSpeed, 0.f, 99999.f); + DDX_Text(pDX, IDC_BRIEF_T_STARTTIME, m_fStartTime); + DDV_MinMaxFloat(pDX, m_fStartTime, 0.f, 99999.f); + DDX_Text(pDX, IDC_BRIEF_T_UL_Y, m_iTY); + DDV_MinMaxInt(pDX, m_iTY, 0, 479); + DDX_Text(pDX, IDC_BRIEF_T_UL_X, m_iLX); + DDV_MinMaxInt(pDX, m_iLX, 0, 639); + DDX_Radio(pDX, IDC_BRIEF_T_STATIC, m_iEffectType); + DDX_Text(pDX, IDC_BRIEF_T_DESC, m_sDesc); + DDX_Text(pDX, IDC_BRIEF_COLOR_B, m_iBlue); + DDX_Text(pDX, IDC_BRIEF_COLOR_G, m_iGreen); + DDX_Text(pDX, IDC_BRIEF_COLOR_R, m_iRed); + DDX_Check(pDX, IDC_TABSTOP, m_TabStop); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CBriefTextEdit, CDialog) + //{{AFX_MSG_MAP(CBriefTextEdit) + ON_BN_CLICKED(IDC_BRIEF_COLOR_PAL, OnBriefColorPal) + ON_CBN_SELCHANGE(IDC_BRIEF_T_PREDEF, OnSelchangeBriefTPredef) + ON_BN_CLICKED(IDC_MISSIONFLAGS, OnMissionflags) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBriefTextEdit message handlers + +void CBriefTextEdit::OnOK() +{ + UpdateData(true); + + //Set window dialog information + desc.caps = TCTD_FONT|TCTD_COLOR|TCTD_SPEED|TCTD_LOOPING|TCTD_WAITTIME|TCTD_TEXTBOX|TCTD_SCROLL; + desc.textbox.bottom = m_iBY; + desc.textbox.right = m_iRX; + desc.textbox.top = m_iTY; + desc.textbox.left = m_iLX; + desc.speed = m_fSpeed; + desc.waittime = m_fStartTime; + desc.color = GR_RGB(m_iRed,m_iGreen,m_iBlue); + + if(m_TabStop) + desc.caps |= TCTD_TABSTOP; + + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_T_FONT); + if(combo->GetCurSel()==1) + desc.font = BBRIEF_FONT_INDEX; + else + desc.font = BRIEF_FONT_INDEX; + + switch(m_iEffectType){ + case 0: + desc.type = TC_TEXT_STATIC; + break; + case 1: + desc.type = TC_TEXT_FLASH; + break; + case 2: + desc.type = TC_TEXT_FADE; + desc.flags = TC_TEXTF_IN; + break; + case 3: + desc.type = TC_TEXT_FADE; + desc.flags = TC_TEXTF_OUT; + break; + case 4: + desc.type = TC_TEXT_SCROLL; + desc.flags = TC_TEXTF_L2R; + break; + case 5: + desc.type = TC_TEXT_SCROLL; + desc.flags = TC_TEXTF_R2L; + break; + case 6: + desc.type = TC_TEXT_SCROLL; + desc.flags = TC_TEXTF_T2B; + break; + case 7: + desc.type = TC_TEXT_SCROLL; + desc.flags = TC_TEXTF_B2T; + break; + }; + + + m_RichEdit.GetWindowText(m_Text); + + CDialog::OnOK(); +} + +BOOL CBriefTextEdit::OnInitDialog() +{ + RECT rect; + CWnd *wnd; + PARAFORMAT pf; + CHARFORMAT cf; + + m_RichEditInit = false; + + CDialog::OnInitDialog(); + +// Create our Rich Edit Control add keyboard handler for those SPECIAL keys like TAB. + wnd = GetDlgItem(IDC_RICHFRAME); + wnd->GetWindowRect(&rect); rect.left += 2; rect.right -= 2; rect.top += 2; rect.bottom-=2; + ScreenToClient(&rect); + m_RichEdit.Create(WS_CHILD | WS_VISIBLE |ES_LEFT + | ES_MULTILINE | ES_WANTRETURN + | ES_AUTOVSCROLL | ES_SAVESEL | ES_NOHIDESEL + | WS_VSCROLL, rect, + this, IDC_SCRIPTVIEW); + m_RichEdit.SetEventMask(ENM_KEYEVENTS | ENM_MOUSEEVENTS); + + + m_RichEdit.LimitText(0); + m_RichEdit.GetParaFormat(pf); + + pf.cbSize = sizeof(pf); + pf.dwMask = PFM_TABSTOPS; + pf.cTabCount = MAX_TAB_STOPS; + for (int i = 0; i < pf.cTabCount; i++) + pf.rgxTabs[i] = 360 * (i+1); + + m_RichEdit.SetParaFormat(pf); + +// sets character format + ZeroMemory(&cf, sizeof(cf)); + cf.dwMask = CFM_FACE | CFM_CHARSET | CFM_BOLD; + strcpy(cf.szFaceName, "Courier"); + cf.bCharSet = DEFAULT_CHARSET; + cf.bPitchAndFamily = FIXED_PITCH | FF_DONTCARE; + m_RichEdit.SetDefaultCharFormat(cf); + + /////////////// + + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_T_FONT); + + combo->AddString("sm_brief"); + combo->AddString("lg_brief"); + + if(desc.font == BRIEF_FONT_INDEX) + combo->SetCurSel(0); + else + combo->SetCurSel(1); + + combo = (CComboBox *)GetDlgItem(IDC_BRIEF_T_PREDEF); + combo->AddString(""); + combo->SetCurSel(0); + + int layout = -1; + + for(i=0;i<(*PBnum_layouts);i++){ + if(!stricmp(Briefing_screens[m_Screen].layout,PBlayouts[i].filename)) + layout = i; + } + + if(layout!=-1){ + int count = PBlayouts[layout].num_texts; + for(int j=0;j(%d,%d)",PBlayouts[layout].texts[j].lx,PBlayouts[layout].texts[j].ty,PBlayouts[layout].texts[j].rx,PBlayouts[layout].texts[j].by); + combo->AddString(buffer); + } + } + + m_RichEdit.SetWindowText((LPCSTR)m_Text.GetBuffer(0)); + + UpdateData(false); + + return TRUE; +} + +void CBriefTextEdit::OnBriefColorPal() +{ + UpdateData(true); + CColorDialog dlg; + + if(dlg.DoModal()==IDOK){ + COLORREF ref; + ref = dlg.GetColor(); + m_iRed = GetRValue(ref); + m_iGreen = GetGValue(ref); + m_iBlue = GetBValue(ref); + } + UpdateData(false); +} + +void CBriefTextEdit::OnSelchangeBriefTPredef() +{ + CComboBox *combo = (CComboBox *)GetDlgItem(IDC_BRIEF_T_PREDEF); + int item = combo->GetCurSel(); + + if(item<=0) + return; + + UpdateData(true); + + int layout = -1; + + for(int i=0;i<(*PBnum_layouts);i++){ + if(!stricmp(Briefing_screens[m_Screen].layout,PBlayouts[i].filename)) + layout = i; + } + + if(layout!=-1){ + m_iLX = PBlayouts[layout].texts[item-1].lx; + m_iTY = PBlayouts[layout].texts[item-1].ty; + m_iRX = PBlayouts[layout].texts[item-1].rx; + m_iBY = PBlayouts[layout].texts[item-1].by; + UpdateData(false); + } +} + +void CBriefTextEdit::OnMissionflags() +{ + CBriefMissionFlagsDlg dlg(desc.mission_mask_set,desc.mission_mask_unset); + + if(dlg.DoModal()){ + desc.mission_mask_set = dlg.m_Set; + desc.mission_mask_unset = dlg.m_UnSet; + } +} diff --git a/editor/BriefTextEdit.h b/editor/BriefTextEdit.h new file mode 100644 index 00000000..2b9be3ae --- /dev/null +++ b/editor/BriefTextEdit.h @@ -0,0 +1,69 @@ +#if !defined(AFX_BRIEFTEXTEDIT_H__01F120A6_427B_11D2_B359_006008BF0B09__INCLUDED_) +#define AFX_BRIEFTEXTEDIT_H__01F120A6_427B_11D2_B359_006008BF0B09__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// BriefTextEdit.h : header file +// +#include "telcomefxstructs.h" +#include "TelComEffects.h" + +///////////////////////////////////////////////////////////////////////////// +// CBriefTextEdit dialog + +class CBriefTextEdit : public CDialog +{ +// Construction +public: + CBriefTextEdit(int curr_screen,LPTCTEXTDESC desc=NULL,char *text=NULL,int id=0,CWnd* pParent = NULL); // standard constructor + TCTEXTDESC desc; + int m_Screen; + CString m_Text; + CRichEditCtrl m_RichEdit; + bool m_RichEditInit; + +// Dialog Data + //{{AFX_DATA(CBriefTextEdit) + enum { IDD = IDD_BRIEF_ADDTEXT }; + int m_iID; + int m_iBY; + int m_iRX; + float m_fSpeed; + float m_fStartTime; + int m_iTY; + int m_iLX; + int m_iEffectType; + CString m_sDesc; + BYTE m_iBlue; + BYTE m_iGreen; + BYTE m_iRed; + BOOL m_TabStop; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBriefTextEdit) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CBriefTextEdit) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnBriefColorPal(); + afx_msg void OnSelchangeBriefTPredef(); + afx_msg void OnMissionflags(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BRIEFTEXTEDIT_H__01F120A6_427B_11D2_B359_006008BF0B09__INCLUDED_) diff --git a/editor/CreateNewScriptDlg.cpp b/editor/CreateNewScriptDlg.cpp new file mode 100644 index 00000000..0bc7a0b0 --- /dev/null +++ b/editor/CreateNewScriptDlg.cpp @@ -0,0 +1,76 @@ +// CreateNewScriptDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "CreateNewScriptDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CCreateNewScriptDlg dialog + + +CCreateNewScriptDlg::CCreateNewScriptDlg(CWnd* pParent /*=NULL*/) + : CDialog(CCreateNewScriptDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CCreateNewScriptDlg) + m_Filename = _T(""); + m_ScriptType = -1; + //}}AFX_DATA_INIT +} + + +void CCreateNewScriptDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CCreateNewScriptDlg) + DDX_Text(pDX, IDC_FILENAME, m_Filename); + DDX_Radio(pDX, IDC_LEVEL, m_ScriptType); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CCreateNewScriptDlg, CDialog) + //{{AFX_MSG_MAP(CCreateNewScriptDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CCreateNewScriptDlg message handlers + +void CCreateNewScriptDlg::OnOK() +{ + UpdateData(true); + + int length = m_Filename.GetLength(); + char *str = m_Filename.GetBuffer(0); + if(length<=0){ + MessageBox("You must specify a filename","Error"); + return; + } + + if((length<=4) || stricmp(&str[length-4],".cpp") ){ + //we need to add a .cpp to the end of the name + m_Filename += ".cpp"; + } + + UpdateData(false); + + CDialog::OnOK(); +} + +BOOL CCreateNewScriptDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_ScriptType = 0; + + UpdateData(false); + + return TRUE; +} diff --git a/editor/CreateNewScriptDlg.h b/editor/CreateNewScriptDlg.h new file mode 100644 index 00000000..4ff4a8cd --- /dev/null +++ b/editor/CreateNewScriptDlg.h @@ -0,0 +1,48 @@ +#if !defined(AFX_CREATENEWSCRIPTDLG_H__7CFE839E_90E9_11D2_AB2B_006008BF0B09__INCLUDED_) +#define AFX_CREATENEWSCRIPTDLG_H__7CFE839E_90E9_11D2_AB2B_006008BF0B09__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// CreateNewScriptDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CCreateNewScriptDlg dialog + +class CCreateNewScriptDlg : public CDialog +{ +// Construction +public: + CCreateNewScriptDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CCreateNewScriptDlg) + enum { IDD = IDD_CREATESCRIPT }; + CString m_Filename; + int m_ScriptType; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CCreateNewScriptDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CCreateNewScriptDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CREATENEWSCRIPTDLG_H__7CFE839E_90E9_11D2_AB2B_006008BF0B09__INCLUDED_) diff --git a/editor/CustDefaultScriptSelect.cpp b/editor/CustDefaultScriptSelect.cpp new file mode 100644 index 00000000..e82d0ab8 --- /dev/null +++ b/editor/CustDefaultScriptSelect.cpp @@ -0,0 +1,75 @@ +// CustDefaultScriptSelect.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "CustDefaultScriptSelect.h" +#include "manage.h" +#include "ddio.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CCustDefaultScriptSelect dialog + + +CCustDefaultScriptSelect::CCustDefaultScriptSelect(CWnd* pParent /*=NULL*/) + : CDialog(CCustDefaultScriptSelect::IDD, pParent) +{ + //{{AFX_DATA_INIT(CCustDefaultScriptSelect) + m_Name = _T(""); + m_Module = _T(""); + //}}AFX_DATA_INIT +} + + +void CCustDefaultScriptSelect::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CCustDefaultScriptSelect) + DDX_Text(pDX, IDC_NAME, m_Name); + DDX_Text(pDX, IDC_MODULE, m_Module); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CCustDefaultScriptSelect, CDialog) + //{{AFX_MSG_MAP(CCustDefaultScriptSelect) + ON_BN_CLICKED(IDC_BROWSE, OnBrowse) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CCustDefaultScriptSelect message handlers + +void CCustDefaultScriptSelect::OnOK() +{ + // TODO: Add extra validation here + + CDialog::OnOK(); +} + +void CCustDefaultScriptSelect::OnBrowse() +{ + + UpdateData(true); + + CString filter = "D3 Compiled Scripts (*.dll)|*.dll||"; + + char filename[_MAX_PATH]; + char pathname[_MAX_PATH],name[_MAX_PATH]; + strcpy(pathname,LocalScriptDir); + + if (!OpenFileDialog(this, (LPCTSTR)filter, filename, pathname, sizeof(pathname))) + return; + + ddio_SplitPath (filename,NULL,name,NULL); + + m_Module = name; + + UpdateData(false); +} diff --git a/editor/CustDefaultScriptSelect.h b/editor/CustDefaultScriptSelect.h new file mode 100644 index 00000000..89262065 --- /dev/null +++ b/editor/CustDefaultScriptSelect.h @@ -0,0 +1,48 @@ +#if !defined(AFX_CUSTDEFAULTSCRIPTSELECT_H__919695A1_B1F3_11D2_AB2B_006008BF0B09__INCLUDED_) +#define AFX_CUSTDEFAULTSCRIPTSELECT_H__919695A1_B1F3_11D2_AB2B_006008BF0B09__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// CustDefaultScriptSelect.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CCustDefaultScriptSelect dialog + +class CCustDefaultScriptSelect : public CDialog +{ +// Construction +public: + CCustDefaultScriptSelect(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CCustDefaultScriptSelect) + enum { IDD = IDD_CUSTDEFSCRIPT }; + CString m_Name; + CString m_Module; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CCustDefaultScriptSelect) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CCustDefaultScriptSelect) + virtual void OnOK(); + afx_msg void OnBrowse(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CUSTDEFAULTSCRIPTSELECT_H__919695A1_B1F3_11D2_AB2B_006008BF0B09__INCLUDED_) diff --git a/editor/CustomObjectDialog.cpp b/editor/CustomObjectDialog.cpp new file mode 100644 index 00000000..3bb8396d --- /dev/null +++ b/editor/CustomObjectDialog.cpp @@ -0,0 +1,43 @@ +// CustomObjectDialog.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "CustomObjectDialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CCustomObjectDialog dialog + + +CCustomObjectDialog::CCustomObjectDialog(CWnd* pParent /*=NULL*/) + : CDialog(CCustomObjectDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CCustomObjectDialog) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CCustomObjectDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CCustomObjectDialog) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CCustomObjectDialog, CDialog) + //{{AFX_MSG_MAP(CCustomObjectDialog) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CCustomObjectDialog message handlers diff --git a/editor/CustomObjectDialog.h b/editor/CustomObjectDialog.h new file mode 100644 index 00000000..aaa7d251 --- /dev/null +++ b/editor/CustomObjectDialog.h @@ -0,0 +1,35 @@ +// CustomObjectDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CCustomObjectDialog dialog + +class CCustomObjectDialog : public CDialog +{ +// Construction +public: + CCustomObjectDialog(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CCustomObjectDialog) + enum { IDD = IDD_CUSTOMIZE_OBJECT }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CCustomObjectDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CCustomObjectDialog) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; diff --git a/editor/D3Splash.cpp b/editor/D3Splash.cpp new file mode 100644 index 00000000..add1c9d1 --- /dev/null +++ b/editor/D3Splash.cpp @@ -0,0 +1,158 @@ +// D3Splash.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "D3Splash.h" + +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +const int SPLASHTEXT_LEFT = 10; +const int SPLASHTEXT_TOP = 180; +const int SPLASHTEXT_RIGHT = 310; +const int SPLASHTEXT_BOTTOM = 230; + +CD3Splash *D3_splash_screen; + +///////////////////////////////////////////////////////////////////////////// +// CD3Splash dialog + + +CD3Splash::CD3Splash(CWnd* pParent /*=NULL*/) + : CDialog(CD3Splash::IDD, pParent) +{ + //{{AFX_DATA_INIT(CD3Splash) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + m_ParentWnd = pParent; +} + + +void CD3Splash::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CD3Splash) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BOOL CD3Splash::Create() +{ + m_TextLines[0][0] = 0; + m_TextLines[1][0] = 0; + m_TextLines[2][0] = 0; + m_CurLine = 0; + + D3_splash_screen = this; + + m_SplashBmp.LoadBitmap(IDB_D3SPLASH); + + return CDialog::Create(CD3Splash::IDD, m_ParentWnd); +} + + +void CD3Splash::PutText(char *buf) +{ + RECT rect; + + if (m_CurLine == 3) { + for (int i = 0; i < 2; i++) + lstrcpy(&m_TextLines[i][0], &m_TextLines[i+1][0]); + } + else m_CurLine++; + + lstrcpy(&m_TextLines[m_CurLine-1][0], buf); + +// mprintf((1, "%d:%s",m_CurLine-1, m_TextLines[m_CurLine-1])); + + SetRect(&rect, SPLASHTEXT_LEFT, SPLASHTEXT_TOP, SPLASHTEXT_RIGHT, SPLASHTEXT_BOTTOM); + InvalidateRect(&rect, FALSE); + UpdateWindow(); +} + + + +BEGIN_MESSAGE_MAP(CD3Splash, CDialog) + //{{AFX_MSG_MAP(CD3Splash) + ON_WM_PAINT() + ON_WM_DESTROY() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CD3Splash message handlers + +void CD3Splash::OnCancel() +{ +// Absolutely nothing +} + + +void CD3Splash::OnOK() +{ +// Absolutely nothing +} + + +void CD3Splash::PostNcDestroy() +{ +// needed for modeless dialogs + delete this; +} + +void CD3Splash::OnPaint() +{ + CPaintDC dc(this); // device context for painting + CDC sdc; // source dc + CBitmap *bmp; + CFont *fnt; + CSize textdim; + BITMAP bm; + RECT uprect; + int x, y; + + GetClientRect(&uprect); + + m_SplashBmp.GetObject(sizeof(bm), &bm); + + sdc.CreateCompatibleDC(NULL); + bmp = sdc.SelectObject(&m_SplashBmp); + dc.StretchBlt(uprect.left+1,uprect.top+1,uprect.right-uprect.left-2,uprect.bottom-uprect.top-2, &sdc, 0,0,bm.bmWidth,bm.bmHeight,SRCCOPY); + sdc.SelectObject(bmp); + + fnt = dc.SelectObject(GetFont()); + dc.SetBkMode(TRANSPARENT); + dc.SetTextColor(RGB(255,255,255)); + + textdim = dc.GetTextExtent(&m_TextLines[0][0], lstrlen(m_TextLines[0])); + + y = uprect.bottom-(4*(textdim.cy+2)); + + for (int r = 0; r < 3; r++) + { + if (lstrlen(m_TextLines[r])) { + textdim = dc.GetTextExtent(&m_TextLines[r][0], lstrlen(m_TextLines[r])); + x = ((uprect.right-uprect.left) - textdim.cx)/2; + dc.TextOut(x,y,&m_TextLines[r][0], lstrlen(m_TextLines[r])); + y += textdim.cy +2; + } + } + dc.SelectObject(fnt); +} + + +void CD3Splash::OnDestroy() +{ + CDialog::OnDestroy(); + + D3_splash_screen = NULL; +} diff --git a/editor/D3Splash.h b/editor/D3Splash.h new file mode 100644 index 00000000..88c87adc --- /dev/null +++ b/editor/D3Splash.h @@ -0,0 +1,56 @@ +// D3Splash.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CD3Splash dialog + +class CD3Splash : public CDialog +{ +// Construction +public: + CD3Splash(CWnd* pParent = NULL); // standard constructor + + BOOL Create(); + +// Dialog Data + //{{AFX_DATA(CD3Splash) + enum { IDD = IDD_D3SPLASH }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CD3Splash) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Operations +public: + void PutText(char *buf); + +private: + char m_TextLines[3][40]; + int m_CurLine; + +// Implementation +protected: + virtual void OnCancel(); + virtual void OnOK(); + + // Generated message map functions + //{{AFX_MSG(CD3Splash) + afx_msg void OnPaint(); + afx_msg void OnDestroy(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +private: + CWnd *m_ParentWnd; + CBitmap m_SplashBmp; +}; + + +extern CD3Splash *D3_splash_screen; diff --git a/editor/D3XStringEditor.cpp b/editor/D3XStringEditor.cpp new file mode 100644 index 00000000..c852dee9 --- /dev/null +++ b/editor/D3XStringEditor.cpp @@ -0,0 +1,222 @@ +/* + * $Logfile: /DescentIII/Main/editor/D3XStringEditor.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:57:37 $ + * $Author: kevinb $ + * + * D3XString Editor + * + * $Log: not supported by cvs2svn $ + * + * 2 9/09/98 12:48p Samir + * added script localizer. + * + * 1 9/09/98 10:29a Samir + * Initial revision. + * + * $NoKeywords: $ + */ + +#include "stdafx.h" +#include "editor.h" +#include "D3XStringEditor.h" +#include "pserror.h" +#include "manage.h" +#include "cfile.h" +#include "d3x.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CD3XStringEditor dialog + + +CD3XStringEditor::CD3XStringEditor(CWnd* pParent /*=NULL*/) + : CDialog(CD3XStringEditor::IDD, pParent) +{ + //{{AFX_DATA_INIT(CD3XStringEditor) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + m_modified = false; + m_cursel = LB_ERR; +} + + +void CD3XStringEditor::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CD3XStringEditor) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CD3XStringEditor, CDialog) + //{{AFX_MSG_MAP(CD3XStringEditor) + ON_BN_CLICKED(IDC_LOADSCRIPT, OnLoadscript) + ON_LBN_SELCHANGE(IDC_STRINGLIST, OnSelchangeStringlist) + ON_LBN_DBLCLK(IDC_STRINGLIST, OnDblclkStringlist) + ON_EN_KILLFOCUS(IDC_STRINGEDIT, OnKillfocusStringedit) + ON_BN_CLICKED(IDC_SAVE, OnSave) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CD3XStringEditor message handlers + +void CD3XStringEditor::OnLoadscript() +{ +// open either a level or a .d3x file + char openpath[PSPATHNAME_LEN+1]; + + if (!PromptSave()) + return; + + if (OpenFileDialog(this, "Descent 3 scripts (*.d3x)|*.d3x||", openpath, LocalLevelsDir, PSPATHNAME_LEN+1)) { + // load program including string table and fill list box will strings. + tD3XProgram *prog; + CListBox *list = (CListBox *)GetDlgItem(IDC_STRINGLIST); + CFILE *fp = cfopen(openpath, "rb"); + + if (!fp) { + OutrageMessageBox("Unable to open %s.", openpath); + return; + } + + prog = D3XLoadProgram(fp); + cfclose(fp); + if (!prog) { + OutrageMessageBox("Illegal d3x file format."); + return; + } + + list->ResetContent(); + for (ushort i = 0; i < prog->nstr; i++) + list->AddString(prog->strlist[i]); + list->EnableWindow(); + + OnSelchangeStringlist(); + + D3XFreeProgram(prog); + + m_pathname = openpath; + m_modified = false; + } +} + +void CD3XStringEditor::OnSelchangeStringlist() +{ + CListBox *list = (CListBox *)GetDlgItem(IDC_STRINGLIST); + CEdit *edit = (CEdit *)GetDlgItem(IDC_STRINGEDIT); + CString str; + int cursel = list->GetCurSel(); + +// replace current string in edit box into this listbox + if (m_cursel != LB_ERR) { + edit->GetWindowText(str); + list->DeleteString(m_cursel); + list->InsertString(m_cursel, str); + m_modified = true; + GetDlgItem(IDC_SAVE)->EnableWindow(); + } + +// put new string into edit box. + if (cursel != LB_ERR) { + list->GetText(cursel, str); + edit->SetWindowText((LPCSTR)str); + edit->EnableWindow(); + } + m_cursel = cursel; +} + +void CD3XStringEditor::OnDblclkStringlist() +{ +} + +void CD3XStringEditor::OnKillfocusStringedit() +{ + m_modified = true; + GetDlgItem(IDC_SAVE)->EnableWindow(); +} + +void CD3XStringEditor::OnSave() +{ + ASSERT(m_modified); + +// save program by loading it in first and reconstructin a new program obhect + CFILE *fp = cfopen(m_pathname, "rb"); + if (fp) { + tD3XProgram *old_prog = D3XLoadProgram(fp); + tD3XProgram *new_prog; + + cfclose(fp); + + if (old_prog) { + CListBox *list = (CListBox *)GetDlgItem(IDC_STRINGLIST); + int curlength = 65536; + char *strbuf = new char[curlength]; + char *strptr; + int i,n = list->GetCount(); + for (i = 0, strptr = strbuf; i < n; i++) + { + CString str; + list->GetText(i, str); + if ((strptr+str.GetLength()+1) > (strbuf+curlength)) { + curlength *= 2; + char *newbuf = new char[curlength]; + strcpy(newbuf, strbuf); + delete[] strbuf; + strbuf = newbuf; + } + strcpy(strptr, str); + strptr += str.GetLength()+1; + } + + new_prog = D3XReallocProgram(NULL, old_prog->len, old_prog->nscripts, old_prog->nstr); + if (new_prog) { + D3XLoadProgramFromComponents(new_prog, old_prog->code, old_prog->map, strbuf); + D3XFreeProgram(old_prog); + fp = cfopen(m_pathname, "wb"); + D3XSaveProgram(fp, new_prog); + cfclose(fp); + D3XFreeProgram(new_prog); + } + else { + OutrageMessageBox("Failed to reallocate new program."); + delete[] strbuf; + return; + } + + delete[] strbuf; + } + } + else { + OutrageMessageBox("Fatal error. Unable to load script file %s.", m_pathname); + return; + } + + + m_modified = false; + GetDlgItem(IDC_SAVE)->EnableWindow(FALSE); + +} + +void CD3XStringEditor::OnOK() +{ + // TODO: Add extra validation here + if (!PromptSave()) + return; + + CDialog::OnOK(); +} + + +bool CD3XStringEditor::PromptSave() +{ + return true; +} diff --git a/editor/D3XStringEditor.h b/editor/D3XStringEditor.h new file mode 100644 index 00000000..ebab2c4b --- /dev/null +++ b/editor/D3XStringEditor.h @@ -0,0 +1,77 @@ +/* + * $Logfile: /DescentIII/Main/editor/D3XStringEditor.h $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:57:37 $ + * $Author: kevinb $ + * + * D3XString Editor + * + * $Log: not supported by cvs2svn $ + * + * 2 9/09/98 12:48p Samir + * added script localizer. + * + * 1 9/09/98 10:37a Samir + * Initial revision. + * + * $NoKeywords: $ + */ + +#if !defined(AFX_D3XSTRINGEDITOR_H__627A6E21_47EE_11D2_B2D5_00A0C94B8467__INCLUDED_) +#define AFX_D3XSTRINGEDITOR_H__627A6E21_47EE_11D2_B2D5_00A0C94B8467__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// D3XStringEditor.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CD3XStringEditor dialog + +class CD3XStringEditor : public CDialog +{ +// Construction +public: + CD3XStringEditor(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CD3XStringEditor) + enum { IDD = IDD_LOCALIZESCRIPT }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CD3XStringEditor) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CD3XStringEditor) + afx_msg void OnLoadscript(); + afx_msg void OnSelchangeStringlist(); + afx_msg void OnDblclkStringlist(); + afx_msg void OnKillfocusStringedit(); + afx_msg void OnSave(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +private: + int m_cursel; // current selection + bool m_modified; + CString m_pathname; + + bool PromptSave(); // returns false if cancelled +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_D3XSTRINGEDITOR_H__627A6E21_47EE_11D2_B2D5_00A0C94B8467__INCLUDED_) diff --git a/editor/DallasFlagDlg.cpp b/editor/DallasFlagDlg.cpp new file mode 100644 index 00000000..79a6e7fb --- /dev/null +++ b/editor/DallasFlagDlg.cpp @@ -0,0 +1,96 @@ +// DallasFlagDlg.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef NEWEDITOR +#include "NewEditor.h" +#else +#include "editor.h" +#endif + +#include "cfile.h" +#include "DallasMainDlg.h" +#include "DallasFlagDlg.h" + +CDallasMainDlg *GetDallasDialogPtr(void); + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDallasFlagDlg dialog + + +CDallasFlagDlg::CDallasFlagDlg(CWnd* pParent /*=NULL*/) + : CDialog(CDallasFlagDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDallasFlagDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_FlagsValue=0; + m_ValidFlagsMask=0; + m_FlagsName=""; +} + + +void CDallasFlagDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDallasFlagDlg) + DDX_Control(pDX, IDC_FLAG_LIST, m_FlagListBox); + DDX_Control(pDX, IDC_FLAG_PROMPT_STATIC, m_FlagPromptText); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDallasFlagDlg, CDialog) + //{{AFX_MSG_MAP(CDallasFlagDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDallasFlagDlg message handlers + +BOOL CDallasFlagDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CDallasMainDlg *m_DallasModelessDlgPtr; + m_DallasModelessDlgPtr = GetDallasDialogPtr(); + + // If Dallas is up, fill in the list box + if(m_DallasModelessDlgPtr!=NULL) { + m_DallasModelessDlgPtr->FillFlagValuesBox(&m_FlagListBox,m_FlagsName.GetBuffer(0),m_FlagsValue,m_ValidFlagsMask); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CDallasFlagDlg::OnOK() +{ + int list_size, j, data; + + // Fill the flags value with checklistbox data + m_FlagsValue=0; + list_size=m_FlagListBox.GetCount(); + for(j=0;j 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DallasFlagDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDallasFlagDlg dialog + +class CDallasFlagDlg : public CDialog +{ +// Construction +public: + CDallasFlagDlg(CWnd* pParent = NULL); // standard constructor + + int m_FlagsValue; + int m_ValidFlagsMask; + CString m_FlagsName; + +// Dialog Data + //{{AFX_DATA(CDallasFlagDlg) + enum { IDD = IDD_DALLAS_FLAG_DIALOG }; + CCheckListBox m_FlagListBox; + CStatic m_FlagPromptText; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDallasFlagDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDallasFlagDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual void OnCancel(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DALLASFLAGDLG_H__DDAEAF22_B1DC_11D2_A4E0_00A0C96ED60D__INCLUDED_) diff --git a/editor/DallasGenericPromptDlg.cpp b/editor/DallasGenericPromptDlg.cpp new file mode 100644 index 00000000..455412ce --- /dev/null +++ b/editor/DallasGenericPromptDlg.cpp @@ -0,0 +1,91 @@ +/* +* $Logfile: /DescentIII/Main/editor/DallasGenericPromptDlg.cpp $ +* $Revision: 1.1.1.1 $ +* $Date: 2003-08-26 03:57:37 $ +* $Author: kevinb $ +* +* This is the header for the DALLAS generic prompt dialog +* +* $Log: not supported by cvs2svn $ + * + * 2 12/13/98 6:08p Nate + * Initial version +* +* $NoKeywords: $ +*/ + +// DallasGenericPromptDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "DallasGenericPromptDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDallasGenericPromptDlg dialog + + +CDallasGenericPromptDlg::CDallasGenericPromptDlg(CWnd* pParent /*=NULL*/) + : CDialog(CDallasGenericPromptDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDallasGenericPromptDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_DialogTitle=""; + m_PromptText=""; + m_PromptData=""; + m_MaxDataLength=10; +} + + +void CDallasGenericPromptDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDallasGenericPromptDlg) + DDX_Control(pDX, IDC_GENERIC_DATA_EDIT, m_GenericDataEdit); + DDX_Control(pDX, IDC_GENERIC_PROMPT_STATIC, m_GenericPromptStatic); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDallasGenericPromptDlg, CDialog) + //{{AFX_MSG_MAP(CDallasGenericPromptDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDallasGenericPromptDlg message handlers + +BOOL CDallasGenericPromptDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + if(!m_DialogTitle.IsEmpty()) + SetWindowText(m_DialogTitle.GetBuffer(0)); + + if(!m_PromptText.IsEmpty()) + m_GenericPromptStatic.SetWindowText(m_PromptText.GetBuffer(0)); + + m_GenericDataEdit.SetLimitText(m_MaxDataLength); + if(!m_PromptData.IsEmpty()) + m_GenericDataEdit.SetWindowText(m_PromptData.GetBuffer(0)); + m_GenericDataEdit.SetSel(0,-1); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CDallasGenericPromptDlg::OnOK() +{ + // TODO: Add extra validation here + m_GenericDataEdit.GetWindowText(m_PromptData); + + CDialog::OnOK(); +} diff --git a/editor/DallasGenericPromptDlg.h b/editor/DallasGenericPromptDlg.h new file mode 100644 index 00000000..a4652512 --- /dev/null +++ b/editor/DallasGenericPromptDlg.h @@ -0,0 +1,70 @@ +/* +* $Logfile: /DescentIII/Main/editor/DallasGenericPromptDlg.h $ +* $Revision: 1.1.1.1 $ +* $Date: 2003-08-26 03:57:37 $ +* $Author: kevinb $ +* +* This is the header for the DALLAS generic prompt dialog +* +* $Log: not supported by cvs2svn $ + * + * 2 12/13/98 6:08p Nate + * Initial version +* +* $NoKeywords: $ +*/ + + +#if !defined(AFX_DALLASGENERICPROMPTDLG_H__94807B41_929B_11D2_A4E0_00A0C96ED60D__INCLUDED_) +#define AFX_DALLASGENERICPROMPTDLG_H__94807B41_929B_11D2_A4E0_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DallasGenericPromptDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDallasGenericPromptDlg dialog + +class CDallasGenericPromptDlg : public CDialog +{ +// Construction +public: + CDallasGenericPromptDlg(CWnd* pParent = NULL); // standard constructor + + CString m_DialogTitle; + CString m_PromptText; + CString m_PromptData; + int m_MaxDataLength; + +// Dialog Data + //{{AFX_DATA(CDallasGenericPromptDlg) + enum { IDD = IDD_DALLAS_GENERIC_PROMPT_DIALOG }; + CEdit m_GenericDataEdit; + CStatic m_GenericPromptStatic; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDallasGenericPromptDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDallasGenericPromptDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DALLASGENERICPROMPTDLG_H__94807B41_929B_11D2_A4E0_00A0C96ED60D__INCLUDED_) diff --git a/editor/DallasImportDlg.cpp b/editor/DallasImportDlg.cpp new file mode 100644 index 00000000..829a6304 --- /dev/null +++ b/editor/DallasImportDlg.cpp @@ -0,0 +1,156 @@ +// DallasImportDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "cfile.h" +#include "DallasMainDlg.h" +#include "DallasUtilities.h" +#include "DallasImportDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDallasImportDlg dialog + + +CDallasImportDlg::CDallasImportDlg(CWnd* pParent /*=NULL*/) + : CDialog(CDallasImportDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDallasImportDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_ScriptName=""; + m_Filename=""; +} + + +void CDallasImportDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDallasImportDlg) + DDX_Control(pDX, IDC_SCRIPT_LIST, m_ScriptListBox); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDallasImportDlg, CDialog) + //{{AFX_MSG_MAP(CDallasImportDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDallasImportDlg message handlers + +void CDallasImportDlg::OnOK() +{ + // TODO: Add extra validation here + int index=m_ScriptListBox.GetCurSel(); + if(index==LB_ERR) return; + + m_ScriptListBox.GetText(index,m_ScriptName); + + CDialog::OnOK(); +} + +void CDallasImportDlg::OnCancel() +{ + // TODO: Add extra cleanup here + + CDialog::OnCancel(); +} + +BOOL CDallasImportDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + FillScriptListBox(m_Filename.GetBuffer(0)); + m_ScriptListBox.SetCurSel(0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +BOOL CDallasImportDlg::FillScriptListBox(char *filename) +{ + CFILE *infile; + char linebuf[2048]; + char *line; + int linenum; + int valid_lines_read; + + // Try to open the file for loading + infile=cfopen (filename,"rt"); + if (!infile) + { + CString msg; + msg.Format("Unable to open \"%s\"!",filename); + MessageBox(msg,"Script Library File Not Found!",MB_OK|MB_ICONEXCLAMATION); + + return FALSE; + } + + linenum=0; + + // Read in and parse each line of the file + while (!cfeof(infile)) { + + // Clear the buffer + strcpy(linebuf,""); + + // Read in a line from the file + cf_ReadString(linebuf, sizeof(linebuf), infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + // Check for Start of Script Block Section + if (strncmp(line,SCRIPT_START_TAG,strlen(SCRIPT_START_TAG)) == 0) { + bool done = false; + + // Set valid line counter to track whether we're reading header info or tree nodes + valid_lines_read=0; + + // Read all the lines in the block + while (!done && !cfeof(infile)) { + + strcpy(linebuf,""); + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + // If it's an empty line or a comment, skip it + if(strlen(line)==0 || strncmp(line,"//",2)==0) + continue; + + // Check for End of Script Block Section + if (strncmp(line,SCRIPT_END_TAG,strlen(SCRIPT_END_TAG)) == 0) { + done=true; + continue; + } + + // See if it should be the script name line + if(valid_lines_read==0) { + m_ScriptListBox.AddString(line); + valid_lines_read++; + continue; + } + } + } + } + + cfclose(infile); + + return TRUE; +} \ No newline at end of file diff --git a/editor/DallasImportDlg.h b/editor/DallasImportDlg.h new file mode 100644 index 00000000..098a995e --- /dev/null +++ b/editor/DallasImportDlg.h @@ -0,0 +1,53 @@ +#if !defined(AFX_DALLASIMPORTDLG_H__B9D24521_BC4B_11D2_A4E0_00A0C96ED60D__INCLUDED_) +#define AFX_DALLASIMPORTDLG_H__B9D24521_BC4B_11D2_A4E0_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DallasImportDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDallasImportDlg dialog + +class CDallasImportDlg : public CDialog +{ +// Construction +public: + CDallasImportDlg(CWnd* pParent = NULL); // standard constructor + + CString m_ScriptName; + CString m_Filename; + + BOOL FillScriptListBox(char *filename); + +// Dialog Data + //{{AFX_DATA(CDallasImportDlg) + enum { IDD = IDD_DALLAS_IMPORT_DIALOG }; + CListBox m_ScriptListBox; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDallasImportDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDallasImportDlg) + virtual void OnOK(); + virtual void OnCancel(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DALLASIMPORTDLG_H__B9D24521_BC4B_11D2_A4E0_00A0C96ED60D__INCLUDED_) diff --git a/editor/DallasMainDlg.cpp b/editor/DallasMainDlg.cpp new file mode 100644 index 00000000..03304c72 --- /dev/null +++ b/editor/DallasMainDlg.cpp @@ -0,0 +1,16365 @@ +/* +* $Logfile: /DescentIII/Main/editor/DallasMainDlg.cpp $ +* $Revision: 1.1.1.1 $ +* $Date: 2003-08-26 03:57:37 $ +* $Author: kevinb $ +* +* This is the code for the main dialog of the DALLAS graphical scripting interface +* +* $Log: not supported by cvs2svn $ + * + * 87 10/23/99 6:16p Nate + * Added support for Polish Message Files + * + * 86 10/08/99 4:55p Nate + * Dallas will now attempt to load the english .msg if a foreign language + * .msg cannot be found + * + * 85 8/31/99 12:05p Nate + * Copy command now displays an "Invalid Copy" message and returns if + * selected item cannot be copied (instead of just copying the entire + * script) + * + * 84 8/30/99 4:11p Nate + * Added copy/paste for conditions, log ops, and nested if-then clauses + * + * 83 6/17/99 10:24a Kevin + * Made things work in a release build + * + * 82 6/09/99 7:05p Jeff + * stub functions added. #ifdef NEWEDITORs added, files changed, to get + * Dallas integrated into new editor + * + * 81 5/21/99 7:32p Nate + * Added Save and Restore ability to the custom script section + * + * 80 5/07/99 10:54a Nate + * Added fix for fitting more scripts in the script type popup menu + * + * 79 5/04/99 6:53p Jeff + * added event for when a player dies + * + * 78 4/27/99 4:27p Jeff + * added player respawn osiris event + * + * 77 4/14/99 6:03p Nate + * Added Event Type specification to Dallas Script Highlighting system. + * + * 76 4/02/99 2:16p Nate + * Added AI Init event + * + * 75 4/01/99 6:02p Nate + * added clipping of long messages when reading them in + * + * 74 3/30/99 4:47p Jeff + * added level events for when IGC occurs for a player + * + * 73 3/17/99 3:57p Nate + * Added localization support for message files, and added level check to + * script grouping system + * + * 72 3/11/99 10:51a Nate + * Added deletion of "Untitled" Dallas files when doing a New from editor + * + * 71 3/03/99 3:07p Nate + * Temporarily allow designer to select named players + * + * 70 3/03/99 12:05a Nate + * Added IT to AI goal complete event, added dynamic message file name + * determination, and made it so you can't select a named player for an + * object type + * + * 69 2/22/99 1:17p Nate + * Added 'level goal item complete' event + * + * 68 2/22/99 1:18a Jeff + * added handling for evt_use + * + * 67 2/20/99 6:07p Nate + * Added Level Goal events + * + * 66 2/19/99 5:35p Nate + * Added new types and events + * + * 65 2/17/99 4:14p Nate + * Added condition query shortcuts + * + * 64 2/17/99 11:36a Nate + * Fixed mprintf in script checksum code + * + * 63 2/17/99 10:57a Nate + * Added script checksum code for Jeff + * + * 62 2/11/99 7:26p Nate + * Added check to save button to make sure editor is up before doing + * anything + * + * 61 2/10/99 1:47p Matt + * Changed object handle symbolic constants + * + * 60 2/08/99 7:40p Nate + * Fixed up event names to reflect IT's + * + * 59 2/08/99 3:53p Nate + * Added new event types + * + * 58 2/07/99 4:43p Nate + * Added OWNER selection to Door parameter types + * + * 57 2/05/99 11:52a Nate + * Added importing/exporting of scripts + * + * 56 2/03/99 7:20p Nate + * Fixed clipboard bug and added script chaining option + * + * 55 2/03/99 2:19p Nate + * Added cool drag-n-drop support + * + * 54 2/03/99 11:57a Nate + * Added script highlighting interface + * + * 53 2/03/99 10:37a Nate + * Max popup items per column is now 40 for Luke + * + * 52 2/02/99 7:41p Nate + * Added columnization of popup menus + * + * 51 2/02/99 8:43a Chris + * I made buildings with AI work correctly (ie really big robots should be + * buildings) + * anim to and from states are now shorts instead of bytes + * + * 50 2/01/99 4:15p Nate + * Changed TIMER HANDLE to TIMER ID to match DallasFuncs + * + * 49 2/01/99 3:48p Nate + * Added fix to INVALID_SCRIPT_ID errors + * + * 48 2/01/99 2:41p Nate + * Added title bar display of level and modified indicator + * + * 47 1/29/99 4:41p Nate + * A few minor tweaks and fixes + * + * 46 1/28/99 9:41p Nate + * Added tons of new stuff + * + * 45 1/26/99 1:15p Nate + * Added UserTypes Workshop implementation + * + * 44 1/25/99 7:16p Nate + * Added UserTypes dialog (non-functional) + * + * 43 1/25/99 2:38p Nate + * Added Valid Flag Mask range support. + * + * 42 1/24/99 4:49p Nate + * Added code for Dallas Save Format Version 1, but didn't enable it yet + * + * 41 1/23/99 5:52p Nate + * Added flag support + * + * 40 1/21/99 8:56p Nate + * Added warnings when saving objects + * + * 39 1/20/99 3:51p Nate + * Added Specific Name parameter type 'a' + * + * 38 1/19/99 7:37p Nate + * Added sound selection prompt dialog + * + * 37 1/19/99 12:18p Nate + * Made it so Owner objects can now be "other" + * + * 36 1/19/99 10:35a Nate + * Fixed Other object submenu bug + * + * 35 1/18/99 2:29p Nate + * Added support for default parameters and valid range specification + * + * 34 1/17/99 6:29p Nate + * Layed groundwork for default parameter values and valid parameter + * ranges + * + * 33 1/15/99 7:31p Nate + * Added some more interface features/fixes + * + * 32 1/15/99 2:05p Nate + * Added collapse/expand all, fixed me and delete problems, made dlg + * longer + * + * 31 1/15/99 10:37a Nate + * Fixed highest room index bug + * + * 30 1/14/99 6:11p Nate + * Added Trigger Script support and many other things, too numerous to + * count. + * + * 29 1/13/99 7:28p Nate + * Added message file reading from created script + * + * 28 1/13/99 10:50a Nate + * Fixed up copy/pase, added highlighting of all scripts matching + * specified owner + * + * 27 1/12/99 7:32p Nate + * Added copy and paste support + * + * 26 1/12/99 4:45p Nate + * Added max exec time support, added more interface features + * + * 25 1/11/99 8:42p Nate + * Added script parameter support + * + * 24 1/11/99 6:40p Nate + * Added ENUM support + * + * 23 1/11/99 10:19a Nate + * Fixed AND/OR insertion bug + * + * 22 1/08/99 12:32p Nate + * Added glue function validation upon loading scripts + * + * 21 1/07/99 10:17p Nate + * Added first round of script loading code... + * + * 20 1/06/99 7:09p Nate + * Added saving of scripts + * + * 19 1/06/99 1:13p Nate + * Added support for IT objects and ELSE clauses + * + * 18 1/05/99 8:00p Nate + * Added conditional code creation... fixed up interface yet a little + * more. + * + * 17 1/05/99 2:03p Nate + * Fixed up events and conditional interface a little + * + * 16 1/04/99 7:34p Nate + * Added rough interface for Conditions + * + * 15 1/02/99 3:22p Matt + * Added support for SaveRestoreState() (new code emailed to me from Jeff) + * + * 14 12/23/98 6:44p Nate + * Added reading in of queries + * + * 13 12/23/98 4:03p Nate + * Added code to implement as a modeless dialog + * + * 12 12/23/98 12:43p Nate + * Fixed small message file parse bug. + * + * 11 12/23/98 12:35p Nate + * Added use of level name in Dallas script file naming system. + * + * 10 12/22/98 3:55p Nate + * Added object and room assignments + * + * 9 12/21/98 8:00p Nate + * Added creation of shell code, started conditional interface. + * + * 8 12/20/98 4:29p Nate + * Added script grouping code (based upon owner, then event type) + * + * 7 12/18/98 3:10p Nate + * Added more interface features. + * + * 6 12/17/98 9:48p Nate + * Added editing of paramaters + * + * 5 12/16/98 8:45p Nate + * Added loading of Actions + * + * 4 12/15/98 7:47p Nate + * Added inserting and deleting of default script trees. + * + * 3 12/13/98 6:08p Nate + * Implemented the Message List interface + * + * 2 12/11/98 6:45p Nate + * Initial Version +* +* $NoKeywords: $ +*/ + +// DallasMainDlg.cpp : implementation file +// + +#include "stdafx.h" + +#include +#include +#include + +#include "pserror.h" +#include "cfile.h" +#include "mem.h" +#include "mono.h" +#include "ddio.h" +#include "manage.h" +#include "object.h" +#include "room.h" +#include "trigger.h" +#include "hlsoundlib.h" +#include "soundload.h" +#include "gametexture.h" +#include "gamepath.h" +#include "matcen.h" +#include "levelgoal.h" + +#ifdef NEWEDITOR +#include "globals.h" +#include "NewEditor.h" +#else +#include "editor.h" +#include "editorDoc.h" +#include "osiris_predefs.h" +#include "descent.h" +#endif + +#include "ScriptCompilerAPI.h" +#include "DallasMainDlg.h" +#include "DallasGenericPromptDlg.h" +#include "DallasVectorPromptDialog.h" +#include "DallasSoundDlg.h" +#include "DallasStrmAudioDlg.h" +#include "DallasTextureDlg.h" +#include "DallasFlagDlg.h" +#include "DallasImportDlg.h" +#include "DallasUserTypesDlg.h" +#include "DallasUtilities.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +//////////////////////////////////////////////////////////////////////////// +// Macro and function to make writing out text to a file a bit easier +#define O(x) OutToFile x +CFILE *CurrentOutputFile; +int CurrentTabLevel; + +// Writes out text to CurrentFile +void OutToFile(char *format, ...) +{ + char buffer[1024]; + + if(CurrentOutputFile==NULL) return; + + va_list marker; + va_start(marker,format); + vsprintf(buffer,format,marker); + cf_WriteString(CurrentOutputFile,buffer); + va_end(marker); +} + +#define DALLASFUNCS_FILENAME "dallasfuncs.cpp" + +#define NOT_SPECIFIED_MSG "" + +#define LEVEL_ID_NAME "ID_LEVEL_0000" +#define LEVEL_CLASS_NAME "LevelScript_0000" + +// Global declaration of event information database +#define UNKNOWN_EVENT_STRING "*Unknown Event*" +#define UNKNOWN_EVENT_CODE_NAME "EVT_UNKNOWN" +#define UNKNOWN_EVENT_DATA_LINE "// No event data line found!" +EventInfoItem event_info[] = { + {COLLIDE_EVENT_TYPE, "Collided (with IT)", "EVT_COLLIDE", "tOSIRISEVTCOLLIDE *event_data=&data->evt_collide;", OBJECT_MASK|HAS_IT_MASK}, + {ACTIVATED_EVENT_TYPE, "Activated (by IT)", "EVT_COLLIDE", "tOSIRISEVTCOLLIDE *event_data=&data->evt_collide;", TRIGGER_MASK|HAS_IT_MASK}, + {CREATED_EVENT_TYPE, "Created", "EVT_CREATED", "tOSIRISEVTCREATED *event_data=&data->evt_created;", OBJECT_MASK}, + {DAMAGED_EVENT_TYPE, "Damaged (by IT)", "EVT_DAMAGED", "tOSIRISEVTDAMAGED *event_data=&data->evt_damaged;", OBJECT_MASK|HAS_IT_MASK}, + {DESTROYED_EVENT_TYPE, "Destroyed", "EVT_DESTROY", "tOSIRISEVTDESTROY *event_data=&data->evt_destroy;", OBJECT_MASK}, + {FRAME_INTERVAL_EVENT_TYPE, "Frame Interval", "EVT_INTERVAL", "tOSIRISEVTINTERVAL *event_data=&data->evt_interval;", OBJECT_MASK|LEVEL_MASK}, + {LEVEL_START_EVENT_TYPE, "Level Start", "EVT_LEVELSTART", "tOSIRISEVTLEVELSTART *event_data=&data->evt_levelstart;", LEVEL_MASK}, + {LEVEL_END_EVENT_TYPE, "Level End", "EVT_LEVELEND", "tOSIRISEVTLEVELEND *event_data=&data->evt_levelend;", LEVEL_MASK}, + {CHANGE_SEGMENT_EVENT_TYPE, "Changed Segment", "EVT_CHANGESEG", "tOSIRISEVTCHANGESEG *event_data=&data->evt_changeseg;", OBJECT_MASK}, + {TIMER_EVENT_TYPE, "Timer (TIMER ID) Went Off", "EVT_TIMER", "tOSIRISEVTTIMER *event_data=&data->evt_timer;", OBJECT_MASK|LEVEL_MASK|HAS_TIMERID_MASK}, + {AI_INIT_EVENT_TYPE, "AI-Initialized", "EVT_AI_INIT", "tOSIRISEVTAIINIT *event_data=&data->evt_ai_init;", OBJECT_MASK}, + {AIN_OBJKILLED_EVENT_TYPE, "AI-Target (IT) Killed", "EVT_AIN_OBJKILLED", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_objkilled;", OBJECT_MASK|HAS_IT_MASK}, + {AIN_SEEPLAYER_EVENT_TYPE, "AI-Saw Target (IT)", "EVT_AIN_SEEPLAYER", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_seeplayer;", OBJECT_MASK|HAS_IT_MASK}, + {AIN_WHITOBJECT_EVENT_TYPE, "AI-Weapon Damaged Target (IT)", "EVT_AIN_WHITOBJECT", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_whitobject;", OBJECT_MASK|HAS_IT_MASK}, + {AIN_GOALCOMPLETE_EVENT_TYPE, "AI-Goal (GOAL ID) Completed (by IT)", "EVT_AIN_GOALCOMPLETE", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_goalcomplete;", OBJECT_MASK|LEVEL_MASK|HAS_GOALID_MASK|HAS_IT_MASK}, + {AIN_GOALFAIL_EVENT_TYPE, "AI-Goal (GOAL ID) Failed", "EVT_AIN_GOALFAIL", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_goalfail;", OBJECT_MASK|LEVEL_MASK|HAS_GOALID_MASK}, + {AIN_MELHIT_EVENT_TYPE, "AI-Melee Hit on Target (IT)", "EVT_AIN_MELEE_HIT", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_melee_hit;", OBJECT_MASK|HAS_IT_MASK}, + {AIN_MELATTACKFRAME_EVENT_TYPE, "AI-Melee Attack Frame", "EVT_AIN_MELEE_ATTACK_FRAME", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_melee_attack_frame;", OBJECT_MASK}, + {AIN_MOVIE_STARTED_EVENT_TYPE, "AI-Movie Started", "EVT_AIN_MOVIE_START", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_movie_start;", OBJECT_MASK}, + {AIN_MOVIE_ENDED_EVENT_TYPE, "AI-Movie Ended", "EVT_AIN_MOVIE_END", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_movie_end;", OBJECT_MASK}, + {CHILD_DIED_EVENT_TYPE, "A Child (IT) Has Died", "EVT_CHILD_DIED", "tOSIRISEVTCHILDDIED *event_data=&data->evt_child_died;", OBJECT_MASK|HAS_IT_MASK}, + {DOOR_CLOSED_EVENT_TYPE, "Door Closed", "EVT_DOOR_CLOSE", "tOSIRISEVTDOORCLOSE *event_data=&data->evt_door_close;", DOOR_OBJECT_MASK}, + {DOOR_ACTIVATED_EVENT_TYPE, "Door Activated", "EVT_DOOR_ACTIVATE", "tOSIRISEVTDOORACTIVATE *event_data=&data->evt_door_activate;", DOOR_OBJECT_MASK}, + {MATCEN_NOTIFY_EVENT_TYPE, "Matcen (MATCEN ID) Has Spawned (an IT)", "EVT_MATCEN_CREATE", "tOSIRISEVTMATCENCREATE *event_data=&data->evt_matcen_create;", LEVEL_MASK|HAS_MATCENID_MASK|HAS_IT_MASK}, + {LGOAL_COMPLETED_EVENT_TYPE, "Level Goal (LEVEL GOAL ID) Completed", "EVT_LEVEL_GOAL_COMPLETE", "tOSIRISEVTLEVELGOALCOMPLETE *event_data=&data->evt_level_goal_complete;", LEVEL_MASK|HAS_LEVGOALID_MASK}, + {LGOAL_ITEM_COMPLETE_EVENT_TYPE, "Level Goal (LEVEL GOAL ID) Item Completed", "EVT_LEVEL_GOAL_ITEM_COMPLETE", "tOSIRISEVTLEVELGOALITEMCOMPLETE *event_data=&data->evt_level_goal_item_complete;", LEVEL_MASK|HAS_LEVGOALID_MASK}, + {ALL_LGOALS_COMPLETE_EVENT_TYPE, "All Level Goals Completed", "EVT_ALL_LEVEL_GOALS_COMPLETE", "tOSIRISEVTALLLEVELGOALSCOMPLETE *event_data=&data->evt_all_level_goals_complete;", LEVEL_MASK}, + {PLAYER_MOVIE_START_TYPE, "Movie Starts With Player Target", "EVT_PLAYER_MOVIE_START", "tOSIRISEVTPLAYERMOVIESTART *event_data=&data->evt_player_movie_start;", LEVEL_MASK}, + {PLAYER_MOVIE_END_TYPE, "Movie Ends With Player Target", "EVT_PLAYER_MOVIE_END", "tOSIRISEVTPLAYERMOVIEEND *event_data=&data->evt_player_movie_end;", LEVEL_MASK}, + {USED_EVENT_TYPE, "Used (by IT)", "EVT_USE", "tOSIRISEVTUSE *event_data=&data->evt_use;", OBJECT_MASK|HAS_IT_MASK}, + {PLAYER_RESPAWN_TYPE, "Player (IT) respawns", "EVT_PLAYER_RESPAWN", "tOSIRISEVTPLAYERRESPAWN *event_data=&data->evt_player_respawn;", LEVEL_MASK|HAS_IT_MASK}, + {PLAYER_DIES_TYPE, "Player (IT) dies", "EVT_PLAYER_DIES", "tOSIRISEVTPLAYERDIES *event_data=&data->evt_player_dies;", LEVEL_MASK|HAS_IT_MASK}, + {-1,"","","",0} +}; + + +// Global declaration of expression operator information database +#define UNKNOWN_EXPOP_STRING "???" +ExpOpInfoItem expop_info[] = { + {EQUAL_TO, "=", "Equal To (==)", "==", COMPARISON_OPERATOR_TYPE}, + {NOT_EQUAL_TO, "!=", "Not Equal To (!=)", "!=", COMPARISON_OPERATOR_TYPE}, + {GREATER_THAN, ">", "Greater Than (>)", ">", COMPARISON_OPERATOR_TYPE}, + {LESS_THAN, "<", "Less Than (<)", "<", COMPARISON_OPERATOR_TYPE}, + {GREATER_THAN_OR_EQUAL_TO, ">=", "Greater Than or Equal To (>=)", ">=", COMPARISON_OPERATOR_TYPE}, + {LESS_THAN_OR_EQUAL_TO, "<=", "Less Than or Equal To (<=)", "<=", COMPARISON_OPERATOR_TYPE}, + {IS_TRUE, "is TRUE", "Is TRUE (!=0)", "==true", BINARY_OPERATOR_TYPE}, + {IS_FALSE, "is FALSE", "Is FALSE (==0)", "==false", BINARY_OPERATOR_TYPE}, + {-1,"","",""} +}; + + +// Global declaration of literal info database +#define UNKNOWN_LITERAL_STRING "UNKNOWN" +ParamMenuItem param_menu_item[] = { + {DOOR_PARAMETER_TYPE,"Door"}, + {OBJECT_PARAMETER_TYPE,"Object"}, + {ROOM_PARAMETER_TYPE,"Room"}, + {TRIGGER_PARAMETER_TYPE,"Trigger"}, + {INT_PARAMETER_TYPE,"Integer"}, + {BOOL_PARAMETER_TYPE,"Bool"}, + {FLOAT_PARAMETER_TYPE,"Float"}, + {VECTOR_PARAMETER_TYPE,"Vector"}, + {STRING_PARAMETER_TYPE,"String"}, + {PERCENTAGE_PARAMETER_TYPE,"Percentage"}, + {ENUM_PARAMETER_TYPE,"Enumerated Types"}, + {SCRIPT_PARAMETER_TYPE,"Script"}, + {SOUND_PARAMETER_TYPE,"Sound"}, + {SPECNAME_PARAMETER_TYPE,"Specific Name"}, + {TEXTURE_PARAMETER_TYPE,"Texture"}, + {FLAG_PARAMETER_TYPE,"Flag"}, + {PATH_PARAMETER_TYPE,"Path"}, + {MATCEN_PARAMETER_TYPE,"Matcen"}, + {LEVEL_GOAL_PARAMETER_TYPE,"Level Goal"}, + {STRM_AUDIO_PARAMETER_TYPE,"Streaming Audio File"}, + {-1,""} +}; + + +#define MAX_MESSAGES 10 // max messages to process during a message deferral + +// Processes and waiting messages +void DeferMsgs(void) +{ + MSG msg; + for ( int MsgCount = MAX_MESSAGES; + MsgCount && PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ); + MsgCount--) { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } +} + +bool Compiling=FALSE; +CString CompilerOutputText=""; +CEdit *help_edit_ctrl=NULL; + +// Gets compiler output and displays it +#define HELP_EDIT_CTRL_HEIGHT 7 +void CompilerCallback(char *text) +{ + CompilerOutputText+=text; + + if(help_edit_ctrl==NULL) return; + help_edit_ctrl->SetWindowText(CompilerOutputText.GetBuffer(0)); + + int total_lines = help_edit_ctrl->GetLineCount(); + int curr_index = help_edit_ctrl->GetFirstVisibleLine(); + if( (total_lines-curr_index)>HELP_EDIT_CTRL_HEIGHT ){ + //we need to scroll down a line + help_edit_ctrl->LineScroll((total_lines-curr_index)-HELP_EDIT_CTRL_HEIGHT); + } + + DeferMsgs(); +} + + +///////////////////////////////////////////////////////////////////////////// +// CDallasMainDlg dialog + + +CDallasMainDlg::CDallasMainDlg(CWnd* pParent /*=NULL*/) + : CDialog(CDallasMainDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDallasMainDlg) + //}}AFX_DATA_INIT + + InitAll(); + + help_edit_ctrl=&m_HelpEdit; + + m_pDragImage=NULL; + m_bLDragging=FALSE; + m_hitemDrag=NULL; + m_hitemDrop=NULL; +} + + +void CDallasMainDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDallasMainDlg) + DDX_Control(pDX, IDC_EVENT_COMBO, m_EventList); + DDX_Control(pDX, IDC_EVENT_TREE, m_ScriptTree); + DDX_Control(pDX, IDC_HELP_EDIT, m_HelpEdit); + DDX_Control(pDX, IDC_MESSAGE_LIST, m_MessageList); + DDX_Control(pDX, IDC_MESSAGE_EDIT, m_MessageEdit); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDallasMainDlg, CDialog) + //{{AFX_MSG_MAP(CDallasMainDlg) + ON_BN_CLICKED(IDC_NEW_MESSAGE_BUTTON, OnNewMessageButton) + ON_BN_CLICKED(IDC_DELETE_MESSAGE_BUTTON, OnDeleteMessageButton) + ON_LBN_SELCHANGE(IDC_MESSAGE_LIST, OnSelchangeMessageList) + ON_EN_CHANGE(IDC_MESSAGE_EDIT, OnChangeMessageEdit) + ON_LBN_DBLCLK(IDC_MESSAGE_LIST, OnDblclkMessageList) + ON_BN_CLICKED(IDC_CHANGE_MESSAGE_NAME_BUTTON, OnChangeMessageNameButton) + ON_WM_CLOSE() + ON_WM_DESTROY() + ON_BN_CLICKED(IDC_NEW_EVENT_BUTTON, OnNewScriptButton) + ON_BN_CLICKED(IDC_INSERT_EVENT_BUTTON, OnInsertScriptButton) + ON_BN_CLICKED(IDC_DELETE_EVENT_BUTTON, OnDeleteScriptButton) + ON_NOTIFY(NM_RCLICK, IDC_EVENT_TREE, OnRclickEventTree) + ON_NOTIFY(NM_DBLCLK, IDC_EVENT_TREE, OnDblclkScriptTree) + ON_NOTIFY(TVN_SELCHANGED, IDC_EVENT_TREE, OnSelchangedScriptTree) + ON_BN_CLICKED(IDC_SAVE_BUTTON, OnSaveButton) + ON_NOTIFY(TVN_KEYDOWN, IDC_EVENT_TREE, OnKeydownEventTree) + ON_BN_CLICKED(IDC_COPY_BUTTON, OnCopyButton) + ON_BN_CLICKED(IDC_PASTE_BUTTON, OnPasteButton) + ON_BN_CLICKED(IDC_HIGHLIGHT_BUTTON, OnHighlightButton) + ON_BN_CLICKED(IDC_EXPAND_ALL_BUTTON, OnExpandAllButton) + ON_BN_CLICKED(IDC_COLLAPSE_ALL_BUTTON, OnCollapseAllButton) + ON_BN_CLICKED(IDC_UTYPES_BUTTON, OnUtypesButton) + ON_NOTIFY(TVN_BEGINDRAG, IDC_EVENT_TREE, OnBegindragEventTree) + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONUP() + ON_BN_CLICKED(IDC_ALLOBJ_RADIO, OnAllobjRadio) + ON_BN_CLICKED(IDC_ALLTRIG_RADIO, OnAlltrigRadio) + ON_BN_CLICKED(IDC_NONE_RADIO, OnNoneRadio) + ON_BN_CLICKED(IDC_SPECIFIC_RADIO, OnSpecificRadio) + ON_BN_CLICKED(IDC_LEVEL_RADIO, OnLevelRadio) + ON_BN_CLICKED(IDC_IMPORT_BUTTON, OnImportButton) + ON_BN_CLICKED(IDC_EXPORT_BUTTON, OnExportButton) + ON_BN_CLICKED(IDC_EVENT_RADIO, OnEventRadio) + ON_CBN_SELCHANGE(IDC_EVENT_COMBO, OnSelchangeEventCombo) + //}}AFX_MSG_MAP + ON_WM_ACTIVATE() + ON_MESSAGE(WM_HIGHLIGHT_SCRIPTS,OnHighlightScripts) + ON_MESSAGE(WM_ADD_SCRIPT,OnAddScript) + ON_MESSAGE(WM_ADD_SCRIPT_AND_HIGHLIGHT,OnAddScriptAndHighlight) + ON_COMMAND_RANGE(ASSIGN_COMMAND_RANGE_START,ASSIGN_COMMAND_RANGE_END,OnMenuSelectionOfTypeAssign) + ON_COMMAND_RANGE(ADD_COMMAND_RANGE_START,ADD_COMMAND_RANGE_END,OnMenuSelectionOfTypeAdd) + ON_COMMAND_RANGE(REPLACE_COMMAND_RANGE_START,REPLACE_COMMAND_RANGE_END,OnMenuSelectionOfTypeReplace) + ON_COMMAND_RANGE(DELETE_COMMAND_RANGE_START,DELETE_COMMAND_RANGE_END,OnMenuSelectionOfTypeDelete) +END_MESSAGE_MAP() + + +// Sets up the dialog before it is displayed +BOOL CDallasMainDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + //CString msg; + //msg.Format("Starting ID: %d\nEnding ID: %d",STARTING_COMMAND_ID,DELETE_COMMAND_RANGE_END); + //MessageBox(msg,"Used ID Range",MB_OK); + + // Setup the tree image list + CBitmap bm; + + m_TreeImageList.Create(16,16,0,19,0); + + bm.LoadBitmap(IDB_DALLAS_TREE_ICONS_BITMAP); + m_TreeImageList.Add(&bm,&bm); + m_ScriptTree.SetImageList(&m_TreeImageList,TVSIL_NORMAL); + + // Setup the Message List GUI and data + m_MessageEdit.SetLimitText(MAX_MESSAGE_LEN); + + + // Make sure everything is cleared out, then load in everything + Refresh(); + Compiling=FALSE; + + //m_ScriptOwnerType=LEVEL_TYPE; + //m_ScriptOwnerHandle=0; + //PostMessage(WM_ADD_SCRIPT_AND_HIGHLIGHT); + + // Set the highlighting to none + ClearHighlightRadioButtons(); + ((CButton *) GetDlgItem(IDC_NONE_RADIO))->SetCheck(1); + OnNoneRadio(); + FillHighlightEventList(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +// Gets called whenever Dallas is activated, allows for validating of script values +void CDallasMainDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) +{ + CDialog::OnActivate(nState,pWndOther,bMinimized); + +#ifndef NEWEDITOR + // Make sure we're in the editor + if(GetFunctionMode()!=EDITOR_MODE) return; +#endif + + if(pWndOther==NULL) return; + + CWnd *parent_window; + parent_window=pWndOther->GetParent(); + + // If Dallas has been activated because it's returned from a child popup, + // then get out of here... + if(parent_window!=NULL) { + if(this->m_hWnd==parent_window->m_hWnd) return; + } + + // Make sure it's been activated, then scan the tree for bad values + if(nState==WA_ACTIVE || nState==WA_CLICKACTIVE) { + ClearNameLists(); + FillNameListsFromTree(TVI_ROOT,FALSE); + } +} + + +// Saves all data +void CDallasMainDlg::OnSaveButton() +{ + CString temp_str; + char fullpath[_MAX_PATH]; + +#ifndef NEWEDITOR + // Make sure we're in the editor + if(GetFunctionMode()!=EDITOR_MODE) return; +#endif + + Compiling=TRUE; + + // Create the script source file + if(!CreateScriptFile(m_ScriptFilename.GetBuffer(0))) { + Compiling=FALSE; + return; + } + SetModified(FALSE); + + // Write out the message list + CreateMsgTableFile(m_ScriptMessagesFilename.GetBuffer(0)); + + // Get the full DLL path, and delete the DLL + ddio_MakePath(fullpath,LocalScriptDir,m_ScriptDLLFilename.GetBuffer(0),NULL); + ddio_DeleteFile(fullpath); + + // Attempt to compile it and create the dll + CompilerOutputText=""; + tCompilerInfo ci; + ci.callback = CompilerCallback; + ci.script_type = ST_LEVEL; + + strcpy(ci.source_filename,m_ScriptFilename.GetBuffer(0)); + ScriptCompile(&ci); + + // Check to see if the DLL has been created + ddio_MakePath(fullpath,LocalScriptDir,m_ScriptDLLFilename.GetBuffer(0),NULL); + if( _access(fullpath,0x00) == -1) { + MessageBox("The compile failed. See output for error details.","Compiler Error"); + } + + Compiling=FALSE; +} + +// Called when the cancel button is pressed +void CDallasMainDlg::OnCancel() +{ + if(Compiling) return; + + if(ModifiedPrompt()==IDNO) return; + + // Shut it all down + DestroyWindow(); + + //CDialog::OnCancel(); +} + +// Called just before the window is destroyed +void CDallasMainDlg::OnDestroy() +{ + CDialog::OnDestroy(); + + // Peform clean-up + ClearAll(); +} + +// Destroy this instance +void CDallasMainDlg::PostNcDestroy() +{ + help_edit_ctrl=NULL; + + // Set the pointer back to null so rest of app knows Dallas has shut down +#ifdef NEWEDITOR + CNewEditorApp *theApp=(CNewEditorApp *)AfxGetApp(); + theApp->DallasDone(); +#else + theApp.m_DallasModelessDlgPtr=NULL; +#endif + + // Delete the Dallas instance + delete this; +} + +// Called before the window is closed +void CDallasMainDlg::OnClose() +{ + if(Compiling) return; + if(ModifiedPrompt()==IDNO) return; + + // Shut it all down + DestroyWindow(); + //CDialog::OnClose(); +} + +// HACK to handle the pressing of the ENTER button (DOESN'T WORK RIGHT NOW) +void CDallasMainDlg::OnOK() +{ + if(Compiling) return; + + HTREEITEM selected_item; + + // Pressing ENTER will now cause an edit popup to appear for selected node + selected_item=m_ScriptTree.GetSelectedItem(); + if(selected_item==NULL) return; + AssignSpecificValue(); +} + +// Launches the UserTypes Dialog +void CDallasMainDlg::OnUtypesButton() +{ + CDallasUserTypesDlg dlg; + + dlg.DoModal(); + + UpdateTreeText(TVI_ROOT); +} + + +///////////////////////////////////////////////////////////////////////////// +// CDallasMainDlg message handlers +///////////////////////////////////////////////////////////////////////////// + +// Adds a new (default) message to the message list +void CDallasMainDlg::OnNewMessageButton() +{ + CString new_name; + + // Create the new name + new_name.Format("%s%d",DEFAULT_MESSAGE_NAME,m_NextMessageID); + + // Make sure the default name isn't already taken + while(FindMessageInList(new_name.GetBuffer(0))!=NULL) { + m_NextMessageID++; + new_name.Format("%s%d",DEFAULT_MESSAGE_NAME,m_NextMessageID); + } + + // Add it to the list + AddToMessageList(new_name.GetBuffer(0),DEFAULT_MESSAGE_TEXT); + m_NextMessageID++; + + // Now let the user change the name if they want to + OnDblclkMessageList(); + + // And then set focus to the message entry box + m_MessageEdit.SetFocus(); + + SetModified(TRUE); +} + +// Deletes the currently selected message from the list +void CDallasMainDlg::OnDeleteMessageButton() +{ + int index; + tMessageListEntry *msg_entry; + + index=m_MessageList.GetCurSel(); + if(index==LB_ERR) return; + + // Get the entry for this item + msg_entry=(tMessageListEntry *)m_MessageList.GetItemData(index); + + // Mark this entry as being free + DeleteMessageListEntry(msg_entry->name); + + // Delete the list box item and update edit boxes + m_MessageList.DeleteString(index); + OnSelchangeMessageList(); + + SetModified(TRUE); +} + +// Callback for when the Message List Box selection changes +void CDallasMainDlg::OnSelchangeMessageList() +{ + int index; + CString name; + tMessageListEntry *msg_entry; + + index=m_MessageList.GetCurSel(); + if(index==LB_ERR) { + m_MessageEdit.SetWindowText(""); + return; + } + + // Get the entry for this item + msg_entry=(tMessageListEntry *)m_MessageList.GetItemData(index); + + // Set the edit boxes to reflect the appropriate data + m_MessageEdit.SetWindowText(msg_entry->message); +} + +// Allows user to change the name of the string +void CDallasMainDlg::OnDblclkMessageList() +{ + CDallasGenericPromptDlg dlg; + int index; + tMessageListEntry *msg_entry; + CString message, old_name; + + index=m_MessageList.GetCurSel(); + if(index==LB_ERR) return; + + // Get the entry for this item + msg_entry=(tMessageListEntry *)m_MessageList.GetItemData(index); + + // Display the prompt dialog + old_name=msg_entry->name; + dlg.m_DialogTitle="Message Name Prompt"; + dlg.m_PromptText="Enter the new name for this message:"; + dlg.m_PromptData=old_name; + dlg.m_MaxDataLength=MAX_MESSAGE_NAME_LEN; + + if(dlg.DoModal()==IDCANCEL) return; + + // Check if the message name is valid + char *msgname=dlg.m_PromptData.GetBuffer(0); + if(strlen(msgname)==0) return; + for(unsigned int j=0;jmessage; + + // Remove the old name from list box + OnDeleteMessageButton(); + + // Now, add the new name (and old message) back in + AddToMessageList(dlg.m_PromptData.GetBuffer(0),message.GetBuffer(0)); + + // Update any old messageID's in the tree to use the new name + UpdateStringParams(TVI_ROOT,old_name.GetBuffer(0),dlg.m_PromptData.GetBuffer(0)); + SetModified(TRUE); +} + +// Does the same thing as double-clicking a name (allows you to change it) +void CDallasMainDlg::OnChangeMessageNameButton() +{ + // TODO: Add your control notification handler code here + OnDblclkMessageList(); +} + +// Updates the text for the message being edited +void CDallasMainDlg::OnChangeMessageEdit() +{ + // TODO: If this is a RICHEDIT control, the control will not + // send this notification unless you override the CDialog::OnInitDialog() + // function and call CRichEditCtrl().SetEventMask() + // with the ENM_CHANGE flag ORed into the mask. + + // TODO: Add your control notification handler code here + int index; + CString name, new_message; + char *message; + + index=m_MessageList.GetCurSel(); + if(index==LB_ERR) return; + + m_MessageList.GetText(index,name); + + message=FindMessageInList(name.GetBuffer(0)); + if(message==NULL) return; + m_MessageEdit.GetWindowText(new_message); + strcpy(message,new_message.GetBuffer(0)); + SetModified(TRUE); +} + + +// Adds a new default script to the end of the list +void CDallasMainDlg::OnNewScriptButton() +{ + HTREEITEM new_node; + + int new_id=GetLowestUnusedScriptID(); + + new_node=CreateDefaultScriptTree(new_id); + if(new_node!=NULL) { + if(new_id==m_NextScriptID) m_NextScriptID++; + m_ScriptTree.SelectItem(new_node); + AssignSpecificValue(); + } +} + + +// Inserts a new default script before the currently selected script +void CDallasMainDlg::OnInsertScriptButton() +{ + HTREEITEM new_node; + + int new_id=GetLowestUnusedScriptID(); + + new_node=CreateDefaultScriptTree(new_id,m_ScriptTree.GetSelectedItem()); + if(new_node!=NULL) { + if(new_id==m_NextScriptID) m_NextScriptID++; + m_ScriptTree.SelectItem(new_node); + AssignSpecificValue(); + } +} + + +// Deletes the currently selected script +void CDallasMainDlg::OnDeleteScriptButton() +{ + HTREEITEM script_header_node; + + script_header_node=GetParentNodeOfType(m_ScriptTree.GetSelectedItem(),SCRIPT_HEADER_NODE); + if(script_header_node==NULL) return; + + if(DeletePrompt("Are you sure you want to delete this script?")==IDYES) { + FreeTreeItem(script_header_node); + SetModified(TRUE); + } +} + + +// Do a script copy +void CDallasMainDlg::OnCopyButton() +{ + PerformScriptCopy(); +} + + +// Do a script paste +void CDallasMainDlg::OnPasteButton() +{ + PerformScriptPaste(); +} + + +// Collapses all node from the selected node on down +void CDallasMainDlg::OnExpandAllButton() +{ + HTREEITEM selected_node; + + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + ExpandAll(selected_node,TVE_EXPAND); + m_ScriptTree.EnsureVisible(selected_node); +} + + +// Collapses all node from the selected node on down +void CDallasMainDlg::OnCollapseAllButton() +{ + HTREEITEM selected_node; + + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + ExpandAll(selected_node,TVE_COLLAPSE); + m_ScriptTree.EnsureVisible(selected_node); +} + + +// Handles the script highlighting +void CDallasMainDlg::OnHighlightButton() +{ + HTREEITEM selected_node, owner_node; + + selected_node=m_ScriptTree.GetSelectedItem(); + owner_node=GetScriptOwnerNode(selected_node); + if(owner_node==NULL) return; + + tTreeNodeData *data=(tTreeNodeData *)m_ScriptTree.GetItemData(owner_node); + if(data==NULL) return; + + m_ScriptOwnerType=data->ID; + m_ScriptOwnerHandle=data->int_val; + + HighlightAllScripts(); + + ClearHighlightRadioButtons(); + ((CButton *) GetDlgItem(IDC_SPECIFIC_RADIO))->SetCheck(1); +} + + +// Calls up edit dialogs when double clicking on a node +void CDallasMainDlg::OnDblclkScriptTree(NMHDR* pNMHDR, LRESULT* pResult) +{ + // TODO: Add your control notification handler code here + + *pResult = 0; +} + + +// Displays a context sensitive pop-up menu +void CDallasMainDlg::OnRclickEventTree(NMHDR* pNMHDR, LRESULT* pResult) +{ + POINT pt; + TVHITTESTINFO hit_info; + + ::GetCursorPos(&pt); + m_ScriptTree.ScreenToClient(&pt); + hit_info.pt=pt; + + // Check to see if the mouse is lined up with a tree item + m_ScriptTree.HitTest(&hit_info); + if(hit_info.flags & TVHT_ONITEM || hit_info.flags & TVHT_ONITEMRIGHT || + hit_info.flags & TVHT_ONITEMINDENT) { + + // Select the item + m_ScriptTree.SelectItem(hit_info.hItem); + + // Convert back to screen coordinates for displaying the menu + m_ScriptTree.ClientToScreen(&pt); + + DisplayFloatingPopupMenu(hit_info.hItem,pt); + } + + *pResult = 0; +} + + +// Displays a context sensitive pop-up menu for the given node at the given screen pt +void CDallasMainDlg::DisplayFloatingPopupMenu(HTREEITEM node, POINT &pt) +{ + int valid_return_type; + CString valid_return_name; + tTreeNodeData *data; + + if(node==NULL) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); + if(data==NULL) return; + + // Call the appropriate Menu Creation function + switch(data->type) { + case SCRIPT_HEADER_NODE: + DisplayScriptHeaderNodeMenu(&pt); + break; + case SCRIPT_OWNER_NODE: + DisplayScriptOwnerNodeMenu(&pt); + break; + case SCRIPT_EVENT_NODE: + DisplayScriptEventNodeMenu(&pt,GetScriptOwnerType(node),ScriptHasADoorMe(node)); + break; + case CONDITIONAL_HEADER_NODE: + break; + case ACTIONS_HEADER_NODE: + DisplayActionHeaderNodeMenu(&pt,data->ID,data->subID,CanAppendElseToNode(node)); + break; + case CONDITIONAL_STATEMENT_NODE: + DisplayConditionalStatementNodeMenu(&pt); + break; + case EXPRESSION_NODE: + valid_return_type=GetValidParamType(node,valid_return_name); + DisplayExpressionNodeMenu(&pt,valid_return_type,valid_return_name.GetBuffer(0)); + break; + case EXPRESSION_OPERATOR_NODE: + DisplayExpressionOperatorNodeMenu(&pt,data->ID); + break; + case ACTION_STATEMENT_NODE: + DisplayActionStatementNodeMenu(&pt); + break; + case LOGICAL_OPERATOR_NODE: + DisplayLogicalOperatorNodeMenu(&pt); + break; + case PARAMETER_NODE: + valid_return_type=GetValidParamType(node,valid_return_name); + DisplayParameterNodeMenu(&pt,data->ID,data->name,valid_return_type,valid_return_name.GetBuffer(0),ScriptHasAnIt(node),ScriptHasAMe(node),ScriptHasADoorMe(node),ScriptHasAGoalID(node),ScriptHasATimerID(node),ScriptHasAMatcenID(node),ScriptHasALevelGoalID(node)); + break; + case PARAMETER_OPERATOR_NODE: + break; + case UNKNOWN_NODE: + break; + default: + break; + } +} + + +// Displays appropriate help for the newly selected item +void CDallasMainDlg::OnSelchangedScriptTree(NMHDR* pNMHDR, LRESULT* pResult) +{ + NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; + + // TODO: Add your control notification handler code here + HTREEITEM selected_item; + tTreeNodeData *data; + + selected_item=m_ScriptTree.GetSelectedItem(); + if(selected_item==NULL) return; + + data=GetNearestFunctionNode(selected_item); + if(data!=NULL) { + // If it's an action node, display the help + if(data->type==ACTION_STATEMENT_NODE) { + char *help=GetActionHelp(data->ID); + if(help!=NULL) m_HelpEdit.SetWindowText(help); + } + + // If it's a query node, display the help + if(data->type==EXPRESSION_NODE) { + char *help=GetQueryHelp(data->ID); + if(help!=NULL) m_HelpEdit.SetWindowText(help); + } + } + + *pResult = 0; +} + + +// Allow keyboard input for the tree control +void CDallasMainDlg::OnKeydownEventTree(NMHDR* pNMHDR, LRESULT* pResult) +{ + TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR; + CTreeCtrl *tree = (CTreeCtrl *)GetDlgItem(pTVKeyDown->hdr.idFrom); + HTREEITEM hSelectedItem = tree->GetSelectedItem(); + + switch (pTVKeyDown->wVKey) + { + case VK_INSERT: + break; + + case VK_DELETE: + break; + + case VK_SPACE: + tree->Expand(hSelectedItem, TVE_TOGGLE); + break; + } + + *pResult = 0; +} + + +///////////////////////////////////////////////////////////////////////////// +// External DALLAS messaging system +///////////////////////////////////////////////////////////////////////////// + + +LONG CDallasMainDlg::OnHighlightScripts(UINT, LONG) +{ + HighlightAllScripts(); + + ClearHighlightRadioButtons(); + ((CButton *) GetDlgItem(IDC_SPECIFIC_RADIO))->SetCheck(1); + + return 0; +} + + +LONG CDallasMainDlg::OnAddScript(UINT, LONG) +{ + HTREEITEM new_node; + + int new_id=GetLowestUnusedScriptID(); + + new_node=CreateDefaultScriptTree(new_id); + if(new_node!=NULL) { + if(new_id==m_NextScriptID) m_NextScriptID++; + m_ScriptTree.SelectItem(new_node); + + // Assign given data to owner + HTREEITEM owner_node=GetScriptOwnerNode(new_node); + if(owner_node!=NULL) { + tTreeNodeData *data=(tTreeNodeData *)m_ScriptTree.GetItemData(owner_node); + if(data!=NULL) { + data->ID=m_ScriptOwnerType; + data->int_val=m_ScriptOwnerHandle; + if(data->ID==OBJECT_TYPE) { + object *objp=ObjGet(data->int_val); + if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { + data->int_val=OBJECT_HANDLE_NONE; + strcpy(data->str_val,""); + } + else { + strcpy(data->str_val,objp->name); + } + } + else if(data->ID==TRIGGER_TYPE) { + if(data->int_val<0 || data->int_val>=Num_triggers) { + data->int_val=NOT_SPECIFIED_TYPE; + strcpy(data->str_val,""); + } + else { + strcpy(data->str_val,Triggers[data->int_val].name); + } + } + else { + strcpy(data->str_val,""); + } + UpdateNodeText(owner_node); + } + } + // Prompt the user for the name of this script + AssignSpecificValue(); + } + return 0; +} + + +LONG CDallasMainDlg::OnAddScriptAndHighlight(UINT, LONG) +{ + HTREEITEM new_node; + + int new_id=GetLowestUnusedScriptID(); + + new_node=CreateDefaultScriptTree(new_id); + if(new_node!=NULL) { + if(new_id==m_NextScriptID) m_NextScriptID++; + m_ScriptTree.SelectItem(new_node); + + // Assign given data to owner + HTREEITEM owner_node=GetScriptOwnerNode(new_node); + if(owner_node!=NULL) { + tTreeNodeData *data=(tTreeNodeData *)m_ScriptTree.GetItemData(owner_node); + if(data!=NULL) { + data->ID=m_ScriptOwnerType; + data->int_val=m_ScriptOwnerHandle; + if(data->ID==OBJECT_TYPE) { + object *objp=ObjGet(data->int_val); + if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { + data->int_val=OBJECT_HANDLE_NONE; + strcpy(data->str_val,""); + } + else { + strcpy(data->str_val,objp->name); + } + } + else if(data->ID==TRIGGER_TYPE) { + if(data->int_val<0 || data->int_val>=Num_triggers) { + data->int_val=NOT_SPECIFIED_TYPE; + strcpy(data->str_val,""); + } + else { + strcpy(data->str_val,Triggers[data->int_val].name); + } + } + else { + strcpy(data->str_val,""); + } + UpdateNodeText(owner_node); + } + } + + // Highlight all the scripts + HighlightAllScripts(); + + ClearHighlightRadioButtons(); + ((CButton *) GetDlgItem(IDC_SPECIFIC_RADIO))->SetCheck(1); + + // Prompt the user for the name of this script + AssignSpecificValue(); + } + return 0; +} + + +// Displays the "are you sure?" dialog +int CDallasMainDlg::ModifiedPrompt(void) +{ + // If current file has been modified, check with user first... + if(!m_Modified) return(IDYES); + if(MessageBox("Your changes will be lost. Proceed?","Script Has Been Modified",MB_YESNO)==IDYES) + return(IDYES); + return(IDNO); +} + + +// Sets the modified flag +void CDallasMainDlg::SetModified(bool value) +{ + m_Modified=value; + SetTitleBar(); +} + + +#define DALLAS_TITLE_STRING "Dallas Graphical Script Editor v1.0" + +// Updates the Dallas title bar +void CDallasMainDlg::SetTitleBar(void) +{ + CString title; + + // Get the current level name + char filename[PSPATHNAME_LEN+1]; + + if(m_ScriptFilename.IsEmpty()) + strcpy(filename,"Untitled"); + else + ddio_SplitPath(m_ScriptFilename.GetBuffer(0),NULL,filename,NULL); + + title.Format("%s - %s%s",DALLAS_TITLE_STRING,filename,(m_Modified) ? "*":""); + SetWindowText(title.GetBuffer(0)); +} + + +///////////////////////////////////////////////////////////////////////////// +// Floating Popup Menu Callbacks +///////////////////////////////////////////////////////////////////////////// + + +// Translates the type of Assign being requested +void CDallasMainDlg::OnMenuSelectionOfTypeAssign(UINT nID) +{ + // Check for the assigning of a message name + if(nID>=ASSIGN_SCRIPT_ID_RANGE_START && nID=ASSIGN_EXEC_TIME_ID_RANGE_START && nID=ASSIGN_CHAIN_ID_RANGE_START && nID=ASSIGN_MESSAGE_ID_RANGE_START && nID=ASSIGN_EVENT_ID_RANGE_START && nID=ASSIGN_TRIGGER_ID_RANGE_START && nID=ASSIGN_OBJECT_ID_RANGE_START && nID=ASSIGN_ROOM_ID_RANGE_START && nID=ASSIGN_EXPOP_ID_RANGE_START && nID=ASSIGN_ENUM_VALUE_ID_RANGE_START && nID=ASSIGN_PATH_ID_RANGE_START && nID=ASSIGN_MATCEN_ID_RANGE_START && nID=ASSIGN_LEVEL_GOAL_ID_RANGE_START && nID=ADD_ACTION_ID_RANGE_START && nID=ADD_LOGOP_ID_RANGE_START && nID=INSERT_LOGOP_ID_RANGE_START && nID=ADD_CONDITION_ID_RANGE_START && nID=ADD_COND_QBIN_ID_RANGE_START && nID=ADD_COND_QCOMP_ID_RANGE_START && nID=REPLACE_QUERY_ID_RANGE_START && nID=REPLACE_LITERAL_ID_RANGE_START && nID=REPLACE_LIT_ENUM_ID_RANGE_START && nID=REPLACE_LIT_FLAG_ID_RANGE_START && nID=REPLACE_ACTION_ID_RANGE_START && nID=REPLACE_LOGOP_ID_RANGE_START && nID=REPLACE_CONDITION_ID_RANGE_START && nID=REPLACE_COND_QBIN_ID_RANGE_START && nID=REPLACE_COND_QCOMP_ID_RANGE_START && nIDtype) { + case ACTION_STATEMENT_NODE: + FreeTreeItem(selected_node); + ConfirmAfterDelete(parent_node); + SetModified(TRUE); + break; + case CONDITIONAL_STATEMENT_NODE: + FreeTreeItem(selected_node); + ConfirmAfterDelete(parent_node); + SetModified(TRUE); + break; + case LOGICAL_OPERATOR_NODE: + FreeTreeItem(selected_node); + ConfirmAfterDelete(parent_node); + SetModified(TRUE); + break; + case ACTIONS_HEADER_NODE: + if(data->ID==NESTED) { + if(data->subID==THEN_CLAUSE) { + HTREEITEM temp_node; + + // Delete the IF clause + temp_node=m_ScriptTree.GetPrevSiblingItem(selected_node); + if(GetNodeType(temp_node)==CONDITIONAL_HEADER_NODE) + FreeTreeItem(temp_node); + + // Delete the ELSE clause (if it exists) + temp_node=m_ScriptTree.GetNextSiblingItem(selected_node); + if(GetNodeType(temp_node)==ACTIONS_HEADER_NODE) + FreeTreeItem(temp_node); + + // Delete the THEN clause + FreeTreeItem(selected_node); + } + else { // Delete just the ELSE clause + FreeTreeItem(selected_node); + } + ConfirmAfterDelete(parent_node); + SetModified(TRUE); + } + break; + } + return; + } + + // Handle Delete children only's + if(nID==DELETE_CHILDREN_ONLY_ID) { + switch(data->type) { + case ACTIONS_HEADER_NODE: + if(DeletePrompt("Are you sure you want to delete all children of this Clause?")==IDYES) { + FreeTreeItemChildren(selected_node); + ConfirmAfterDelete(selected_node); + SetModified(TRUE); + } + break; + } + return; + } +} + + +// Displays a deletion prompt +int CDallasMainDlg::DeletePrompt(char *msg) +{ + CString title="Deletion Prompt"; + return(MessageBox(msg,title.GetBuffer(0),MB_YESNO|MB_ICONQUESTION)); +} + + +// Makes sure everything is as it should be after a delete +void CDallasMainDlg::ConfirmAfterDelete(HTREEITEM parent) +{ + tTreeNodeData *data; + HTREEITEM new_node; + + if(parent==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(parent); + if(data==NULL) return; + + // Make sure IF statement has one child! + if(data->type==CONDITIONAL_HEADER_NODE) { + if(GetChildCount(parent)!=1) { + FreeTreeItemChildren(parent); + new_node=CreateDefaultConditionalStatementNode(parent); + if(new_node!=NULL) m_ScriptTree.SelectItem(new_node); + } + return; + } + + // Make sure THEN statement has at least one child + if(data->type==ACTIONS_HEADER_NODE) { + if(GetChildCount(parent)==0) { + new_node=CreateDefaultActionStatementNode(parent); + if(new_node!=NULL) m_ScriptTree.SelectItem(new_node); + } + return; + } + + // Make sure Logical operators have right number of children + if(data->type==LOGICAL_OPERATOR_NODE) { + if(data->ID==AND_TYPE || data->ID==OR_TYPE) { + if(GetChildCount(parent)<2) { + new_node=CreateDefaultConditionalStatementNode(parent); + if(new_node!=NULL) m_ScriptTree.SelectItem(new_node); + } + } + return; + } +} + + +///////////////////////////////////////////////////////////////////////////// +// General Refresh functions +///////////////////////////////////////////////////////////////////////////// + + +// Performs all basic initialization tasks +void CDallasMainDlg::InitAll(void) +{ + m_Modified=FALSE; + + InitTree(); + InitMessageList(); + InitEnumDatabase(); + InitFlagDatabase(); + InitFunctionDatabases(); + InitScriptGroupingList(); + InitObjectHandleList(); + InitCustomScriptStorage(); + InitNameLists(); + + CurrentOutputFile=NULL; + CurrentTabLevel=0; + + m_ScriptOwnerType=NONE_TYPE; + m_ScriptOwnerHandle=0; +} + + +// Frees up all DALLAS memory +void CDallasMainDlg::ClearAll(void) +{ + ClearMessageList(); + ClearEnumDatabase(); + ClearFlagDatabase(); + ClearFunctionDatabases(); + ClearTree(); + ClearScriptGroupingList(); + ClearObjectHandleList(); + ClearCustomScriptStorage(); + ClearNameLists(); +} + + +// Loads in everything +void CDallasMainDlg::LoadAll(void) +{ + // Parse the message file (string table) for this level + ParseMsgTableFile(m_ScriptMessagesFilename.GetBuffer(0)); + + // Parse actions into the Action Database + ParseFunctionFile(m_DallasFunctionsFilename.GetBuffer(0)); + ParseFunctionFile(m_ScriptFilename.GetBuffer(0),FALSE); + + // Read in the saved script tree + ParseSourceScript(m_ScriptFilename.GetBuffer(0)); + + // Read in the custom script text + ParseCustomScriptFile(m_ScriptFilename.GetBuffer(0),FALSE); +} + + +// Sets all the filenames to match the currently loaded level +void CDallasMainDlg::SetAllFilenames(void) +{ + // Set the Dallas Functions Filename + m_DallasFunctionsFilename=DALLASFUNCS_FILENAME; + + // Get the current level name + char filename[PSPATHNAME_LEN+1]; + + CString level_fname; +#ifdef NEWEDITOR + level_fname = Level_name; +#else + level_fname = theApp.main_doc->GetPathName(); +#endif + + if(level_fname.IsEmpty()) + strcpy(filename,"Untitled"); + else + ddio_SplitPath(level_fname.GetBuffer(0),NULL,filename,NULL); + + // Create the script source filename + m_ScriptFilename.Format("%s.cpp",filename); + + // Create the script DLL filename + m_ScriptDLLFilename.Format("%s.dll",filename); + + // Create the message table filename + m_ScriptMessagesFilename.Format("%s.msg",filename); +} + + +// Sets all the filenames to match the given level name +void CDallasMainDlg::SetAllFilenamesToThis(char *level_path) +{ + if(level_path==NULL) return; + + // Set the Dallas Functions Filename + m_DallasFunctionsFilename=DALLASFUNCS_FILENAME; + + // Get the current level name + char filename[PSPATHNAME_LEN+1]; + + CString level_fname; + level_fname = level_path; + + if(level_fname.IsEmpty()) + strcpy(filename,"Untitled"); + else + ddio_SplitPath(level_fname.GetBuffer(0),NULL,filename,NULL); + + // Create the script source filename + m_ScriptFilename.Format("%s.cpp",filename); + + // Create the script DLL filename + m_ScriptDLLFilename.Format("%s.dll",filename); + + // Create the message table filename + m_ScriptMessagesFilename.Format("%s.msg",filename); + + // Reflect changes in the title bar + SetTitleBar(); +} + + +// Does a complete refresh of DALLAS +void CDallasMainDlg::Refresh(void) +{ + // Make sure everything is cleared out + ClearAll(); + + // Set all the filenames to match the currently loaded level + SetAllFilenames(); + + // Load in everything + LoadAll(); + + // Highlight the appropriate scripts + HighlightAllScripts(); + + SetModified(FALSE); +} + + +///////////////////////////////////////////////////////////////////////////// +// Manage System functions +///////////////////////////////////////////////////////////////////////////// + + +void CDallasMainDlg::CheckinScriptFiles(void) +{ +} + + +void CDallasMainDlg::CheckoutScriptFiles(void) +{ +} + + +void CDallasMainDlg::DeleteScriptFiles(void) +{ +} + + +///////////////////////////////////////////////////////////////////////////// +// Tree Control Functions +///////////////////////////////////////////////////////////////////////////// + + +// Performs any necessary initialization of the tree control (and node data) +void CDallasMainDlg::InitTree(void) +{ + m_NextScriptID=0; + m_ClipboardNode=NULL; +} + + +// Performs any necessary de-initialization of the tree control (and node data) +void CDallasMainDlg::ClearTree(void) +{ + FreeTreeItemChildren(TVI_ROOT); + m_NextScriptID=0; + m_ClipboardNode=NULL; +} + + +// Obtains the string name for an event type +char *CDallasMainDlg::GetEventTypeString(int type) +{ + for(int j=0;event_info[j].type>=0;j++) + if(event_info[j].type==type) + return(event_info[j].name); + + return(UNKNOWN_EVENT_STRING); +} + + +// Updates the text for every node in the tree +void CDallasMainDlg::UpdateTreeText(HTREEITEM parent) +{ + HTREEITEM child; + + if(parent==NULL) return; + + // Process the children + child=m_ScriptTree.GetChildItem(parent); + while(child!=NULL) { + UpdateTreeText(child); + UpdateNodeText(child); + + // Get the next child + child=m_ScriptTree.GetNextSiblingItem(child); + } +} + + +// Obtains the in-code DEFINE name for an event type +char *CDallasMainDlg::GetEventCodeName(int type) +{ + for(int j=0;event_info[j].type>=0;j++) + if(event_info[j].type==type) + return(event_info[j].code_name); + + return(UNKNOWN_EVENT_CODE_NAME); +} + + +// Obtains the data line for an event type +char *CDallasMainDlg::GetEventDataLine(int type) +{ + for(int j=0;event_info[j].type>=0;j++) + if(event_info[j].type==type) + return(event_info[j].data_line); + + return(UNKNOWN_EVENT_DATA_LINE); +} + + +// Obtains the string name for a logical operator type +void CDallasMainDlg::GetLogicalOperatorTypeString(int type, CString &string) +{ + switch(type) { + case AND_TYPE: + string="AND"; + break; + case OR_TYPE: + string="OR"; + break; + default: + string="Unknown"; + break; + } +} + + +// Checks to see if the given script has an IT (based upon the event type) +bool CDallasMainDlg::ScriptHasAnIt(HTREEITEM script_node) +{ + // Check the owner type (only triggers and objects can have an it) + //int owner_type=GetScriptOwnerType(script_node); + //if(owner_type!=OBJECT_TYPE && owner_type!=TRIGGER_TYPE) + // return FALSE; + + // Check the script's event type + int event_type=GetScriptEventType(script_node); + + for(int j=0;event_info[j].type>=0;j++) + if(event_info[j].type==event_type) { + if(event_info[j].flags & HAS_IT_MASK) + return TRUE; + else + return FALSE; + } + + return FALSE; +} + + +// Checks to see if the given script has an ME (based upon the event type) +bool CDallasMainDlg::ScriptHasAMe(HTREEITEM script_node) +{ + // Check the owner type (only an object owner can have a me) + int owner_type=GetScriptOwnerType(script_node); + if(owner_type!=OBJECT_TYPE) + return FALSE; + + return TRUE; +} + + +// Checks to see if the given script has a ME of type DOOR (based upon the event type) +bool CDallasMainDlg::ScriptHasADoorMe(HTREEITEM script_node) +{ + HTREEITEM owner_node; + tTreeNodeData *data; + + owner_node=GetScriptOwnerNode(script_node); + if(owner_node==NULL) return(FALSE); + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(owner_node); + if(data==NULL) return(FALSE); + + // Check the owner type (only an object owner can have a me) + if(data->ID!=OBJECT_TYPE) + return FALSE; + + // Make sure it's a Door object + object *objp=ObjGet(data->int_val); + if(objp==NULL || objp->type!=OBJ_DOOR || objp->name==NULL) + return FALSE; + + return TRUE; +} + + +// Checks to see if the given script has an GoalID (based upon the event type) +bool CDallasMainDlg::ScriptHasAGoalID(HTREEITEM script_node) +{ + // Check the owner type (only levels and objects can have a GoalID) + int owner_type=GetScriptOwnerType(script_node); + if(owner_type!=OBJECT_TYPE && owner_type!=LEVEL_TYPE) + return FALSE; + + // Check the script's event type + int event_type=GetScriptEventType(script_node); + + for(int j=0;event_info[j].type>=0;j++) + if(event_info[j].type==event_type) { + if(event_info[j].flags & HAS_GOALID_MASK) + return TRUE; + else + return FALSE; + } + + return FALSE; +} + + +// Checks to see if the given script has a Timer ID (based upon the event type) +bool CDallasMainDlg::ScriptHasATimerID(HTREEITEM script_node) +{ + // Check the owner type (only levels and objects can have a MatcenID) + int owner_type=GetScriptOwnerType(script_node); + if(owner_type!=OBJECT_TYPE && owner_type!=LEVEL_TYPE) + return FALSE; + + // Check the script's event type + int event_type=GetScriptEventType(script_node); + + for(int j=0;event_info[j].type>=0;j++) + if(event_info[j].type==event_type) { + if(event_info[j].flags & HAS_TIMERID_MASK) + return TRUE; + else + return FALSE; + } + + return FALSE; +} + + +// Checks to see if the given script has a Matcen ID (based upon the event type) +bool CDallasMainDlg::ScriptHasAMatcenID(HTREEITEM script_node) +{ + // Check the owner type (only levels and objects can have a MatcenID) + int owner_type=GetScriptOwnerType(script_node); + if(owner_type!=OBJECT_TYPE && owner_type!=LEVEL_TYPE) + return FALSE; + + // Check the script's event type + int event_type=GetScriptEventType(script_node); + + for(int j=0;event_info[j].type>=0;j++) + if(event_info[j].type==event_type) { + if(event_info[j].flags & HAS_MATCENID_MASK) + return TRUE; + else + return FALSE; + } + + return FALSE; +} + + +// Checks to see if the given script has a Level Goal ID (based upon the event type) +bool CDallasMainDlg::ScriptHasALevelGoalID(HTREEITEM script_node) +{ + // Check the owner type (only levels and objects can have a MatcenID) + int owner_type=GetScriptOwnerType(script_node); + if(owner_type!=LEVEL_TYPE) + return FALSE; + + // Check the script's event type + int event_type=GetScriptEventType(script_node); + + for(int j=0;event_info[j].type>=0;j++) + if(event_info[j].type==event_type) { + if(event_info[j].flags & HAS_LEVGOALID_MASK) + return TRUE; + else + return FALSE; + } + + return FALSE; +} + + +// Checks to see if a given node is a clause of the given type +bool CDallasMainDlg::NodeIsIfClause(HTREEITEM node) +{ + tTreeNodeData *data; + + if(node==NULL) return(FALSE); + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); + if(data==NULL || data->type!=CONDITIONAL_HEADER_NODE) return(FALSE); + + if(data->ID!=NESTED) return(FALSE); + + return(TRUE); +} + +// Checks to see if a given node is a clause of the given type +bool CDallasMainDlg::NodeIsClauseOfType(HTREEITEM node, int type) +{ + tTreeNodeData *data; + + if(node==NULL) return(FALSE); + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); + if(data==NULL || data->type!=ACTIONS_HEADER_NODE) return(FALSE); + + if(data->ID!=NESTED) return(FALSE); + if(data->subID!=type) return(FALSE); + + return(TRUE); +} + +// Checks to see if it's ok to add an else clause to the given node +bool CDallasMainDlg::CanAppendElseToNode(HTREEITEM node) +{ + HTREEITEM next_node; + + // Make sure given node is a nested THEN + if(!NodeIsClauseOfType(node,THEN_CLAUSE)) return(FALSE); + + // Make sure this node doesn't already have an else + next_node=m_ScriptTree.GetNextSiblingItem(node); + if(NodeIsClauseOfType(next_node,ELSE_CLAUSE)) return(FALSE); + + return(TRUE); +} + + +// Obtains the string name for an expression operator type +char *CDallasMainDlg::GetExpressionOperatorTypeString(int type) +{ + for(int j=0;expop_info[j].type>=0;j++) + if(expop_info[j].type==type) + return(expop_info[j].name); + + return(UNKNOWN_EXPOP_STRING); +} + + +// Obtains the string name for an expression operator type +char *CDallasMainDlg::GetExpressionOperatorCodeName(int type) +{ + for(int j=0;expop_info[j].type>=0;j++) + if(expop_info[j].type==type) + return(expop_info[j].code_name); + + return(UNKNOWN_EXPOP_STRING); +} + + +// Obtains the string name for a literal +char *CDallasMainDlg::GetLiteralName(int type) +{ + for(int j=0;param_menu_item[j].type>=0;j++) + if(param_menu_item[j].type==type) + return(param_menu_item[j].name); + + return(UNKNOWN_LITERAL_STRING); +} + + +// Updates the text display of the given node +void CDallasMainDlg::UpdateNodeText(HTREEITEM node) +{ + CString new_text; + tTreeNodeData *data; + + if(node==NULL) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); + if(data==NULL) return; + + // Format and set the new text + FormatTreeText(new_text,data,node); + m_ScriptTree.SetItemText(node,new_text.GetBuffer(0)); +} + + +// Updates the text of given node and all parent nodes above the given node +void CDallasMainDlg::UpdateAllParentNodesText(HTREEITEM node) +{ + HTREEITEM parent; + + if(node==NULL) return; + + UpdateNodeText(node); + + parent=m_ScriptTree.GetParentItem(node); + while(parent!=NULL) { + UpdateNodeText(parent); + parent=m_ScriptTree.GetParentItem(parent); + } +} + + +// Formats the given string according to the given node data +void CDallasMainDlg::FormatTreeText(CString &text, tTreeNodeData *data, HTREEITEM node/*=NULL*/) +{ + CString tmp_str1, tmp_str2; + object *objp; + + // Make sure given data is valid + if(data==NULL) return; + + // Format the text according to the tree node type + switch(data->type) { + case SCRIPT_HEADER_NODE: + text.Format("Script %.03d: %s",data->ID,data->name); + break; + case SCRIPT_OWNER_NODE: + switch(data->ID) { + case OBJECT_TYPE: + if(data->int_val == OBJECT_HANDLE_NONE) { + text.Format("Owner: %s (Object)",NONE_STRING); + break; + } + objp=ObjGet(data->int_val); + if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) + text.Format("Owner: *OBJECT_ERROR*"); + else + text.Format("Owner: %s (Object)",objp->name); + break; + case TRIGGER_TYPE: + if(data->int_val == NOT_SPECIFIED_TYPE) { + text.Format("Owner: %s (Trigger)",NOT_SPECIFIED_STRING); + break; + } + if(data->int_val<0 || data->int_val>=Num_triggers) + text.Format("Owner: *INVALID_TRIGGER*"); + else + text.Format("Owner: %s (Trigger)",Triggers[data->int_val].name); + break; + case LEVEL_TYPE: + text.Format("Owner: Level"); + break; + default: + text.Format("Owner: %s",NOT_SPECIFIED_STRING); + break; + } + break; + case SCRIPT_EVENT_NODE: + text.Format("Event: %s",GetEventTypeString(data->ID)); + break; + case CONDITIONAL_HEADER_NODE: + text.Format("If the following condition is met:"); + break; + case ACTIONS_HEADER_NODE: + if(data->ID==TOP_LEVEL && data->int_val==BREAK_SCRIPT_CHAIN) + tmp_str2=" and BREAK script chain"; + else + tmp_str2=""; + if(data->ID==TOP_LEVEL && data->subID==1) + tmp_str1.Format(" (only do once%s)",tmp_str2); + else if(data->ID==TOP_LEVEL && data->subID==2) + tmp_str1.Format(" (only do twice%s)",tmp_str2); + else if(data->ID==TOP_LEVEL && data->subID>=3) + tmp_str1.Format(" (only do %d times%s)",data->subID,tmp_str2); + else + tmp_str1.Format("%s",tmp_str2); + if(data->ID==NESTED && data->subID==ELSE_CLAUSE) + text.Format("Else, perform these actions:"); + else + text.Format("Then perform the following actions%s:",tmp_str1); + break; + case CONDITIONAL_STATEMENT_NODE: + if(data->ID==ALWAYS_STATEMENT) + text.Format("%s",ALWAYS_STRING); + else + FormatConditionText(text,node); + break; + case EXPRESSION_NODE: + FormatQueryNodeText(tmp_str1,node); + text.Format("%s: %s",data->name,tmp_str1); + break; + case EXPRESSION_OPERATOR_NODE: + text.Format("Operation: %s",GetExpressionOperatorTypeString(data->subID)); + break; + case ACTION_STATEMENT_NODE: + if(data->ID==DO_NOTHING_ID) + text.Format("%s",DO_NOTHING_STRING); + else + FormatActionNodeText(text,node); + break; + case LOGICAL_OPERATOR_NODE: + GetLogicalOperatorTypeString(data->ID,tmp_str1); + text.Format("%s",tmp_str1); + break; + case PARAMETER_NODE: + FormatParameterValueText(tmp_str1,data); + text.Format("%s: %s",data->name, tmp_str1.GetBuffer(0)); + break; + case PARAMETER_OPERATOR_NODE: + text.Format("this is a parameter operator"); + break; + case CLIPBOARD_HEADER_NODE: + text.Format("Clipboard"); + break; + case UNKNOWN_NODE: + text.Format("Unknown Type"); + break; + default: + text.Format("REALLY Unknown Type"); + break; + } +} + + +// Formats the text for a Conditional Statement according to it and its children +void CDallasMainDlg::FormatConditionText(CString &text, HTREEITEM condition_node) +{ + tTreeNodeData *data; + HTREEITEM child_node; + + // Make sure given node is valid + if(condition_node==NULL) { + text="*ERROR*"; + return; + } + + // Get node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(condition_node); + if(data==NULL) { + text="*ERROR*"; + return; + } + + // Make sure given data node is a conditional statement node + if(data->type!=CONDITIONAL_STATEMENT_NODE) { + text=""; + return; + } + + text="("; + + // Get the first child (literal or query) + child_node=m_ScriptTree.GetChildItem(condition_node); + if(child_node!=NULL) { + CString temp_str; + FormatGenericExpressionText(temp_str,child_node); + text+=temp_str; + } + else { + text+="???"; + } + + text+=") "; + + // Get the second child (expression operator) + if(child_node!=NULL) { + child_node=m_ScriptTree.GetNextSiblingItem(child_node); + if(child_node!=NULL) { + CString temp_str; + FormatGenericExpressionText(temp_str,child_node); + text+=temp_str; + } + else { + text+="???"; + } + } + + // If it's a comparison, get the third child (literal or query) + if(child_node!=NULL && data->ID==COMPARISON_STATEMENT) { + child_node=m_ScriptTree.GetNextSiblingItem(child_node); + if(child_node!=NULL) { + CString temp_str; + FormatGenericExpressionText(temp_str,child_node); + text+=" ("; + text+=temp_str; + text+=")"; + } + else { + text+=" (???)"; + } + } +} + + +// Formats a child node of a conditional statement node +void CDallasMainDlg::FormatGenericExpressionText(CString &text, HTREEITEM gen_exp_node) +{ + tTreeNodeData *data; + + // Make sure given node is valid + if(gen_exp_node==NULL) { + text="*ERROR*"; + return; + } + + // Get node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(gen_exp_node); + if(data==NULL) { + text="*ERROR*"; + return; + } + + // See if it's a parameter node + if(data->type==PARAMETER_NODE) { + FormatParameterValueText(text,data); + return; + } + + // See if it's a query node + if(data->type==EXPRESSION_NODE) { + FormatQueryNodeText(text,gen_exp_node); + return; + } + + // See if it's an expression operator node + if(data->type==EXPRESSION_OPERATOR_NODE) { + text.Format("%s",GetExpressionOperatorTypeString(data->subID)); + return; + } + + text=""; +} + + +// Formats the text for a Parameter Value according to the given node data +void CDallasMainDlg::FormatParameterValueText(CString &text, tTreeNodeData *data) +{ + object *objp; + char *temp_str; + char temp_name[MAX_PATH+1]; + + // Make sure given data is valid + if(data==NULL) { + text=""; + return; + } + + // Make sure given data node is a parameter node + if(data->type!=PARAMETER_NODE) { + text=""; + return; + } + + // Format the text according to the parameter type and value data + switch(data->ID) { + case DOOR_PARAMETER_TYPE: + if(data->subID == USE_ME_HANDLE) { + text.Format("OWNER"); + break; + } + if(data->int_val == OBJECT_HANDLE_NONE) { + text.Format("%s",NONE_STRING); + break; + } + objp=ObjGet(data->int_val); + if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) + text.Format("*DOOR_ERROR*"); + else + text.Format("%s",objp->name); + break; + case OBJECT_PARAMETER_TYPE: + if(data->subID == USE_IT_HANDLE) { + text.Format("IT"); + break; + } + if(data->subID == USE_ME_HANDLE) { + text.Format("OWNER"); + break; + } + if(data->int_val == OBJECT_HANDLE_NONE) { + text.Format("%s",NONE_STRING); + break; + } + objp=ObjGet(data->int_val); + if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) + text.Format("*OBJECT_ERROR*"); + else + text.Format("%s",objp->name); + break; + case ROOM_PARAMETER_TYPE: + if(data->int_val == NOT_SPECIFIED_TYPE) { + text.Format("%s",NOT_SPECIFIED_STRING); + break; + } + if(data->int_val<0 || data->int_val>Highest_room_index) + text.Format("*INVALID_ROOM*"); + else + text.Format("%s",Rooms[data->int_val].name); + break; + case TRIGGER_PARAMETER_TYPE: + if(data->int_val == NOT_SPECIFIED_TYPE) { + text.Format("%s",NOT_SPECIFIED_STRING); + break; + } + if(data->int_val<0 || data->int_val>=Num_triggers) + text.Format("*INVALID_TRIGGER*"); + else + text.Format("%s",Triggers[data->int_val].name); + break; + case INT_PARAMETER_TYPE: + text.Format("%d",data->int_val); + break; + case BOOL_PARAMETER_TYPE: + if(data->int_val) + text.Format("TRUE"); + else + text.Format("FALSE"); + break; + case FLOAT_PARAMETER_TYPE: + text.Format("%.2f",data->float_val1); + break; + case VECTOR_PARAMETER_TYPE: + text.Format("<%.2f,%.2f,%.2f>",data->float_val1,data->float_val2,data->float_val3); + break; + case STRING_PARAMETER_TYPE: + if(strlen(data->str_val)==0) + text.Format("No ID Chosen"); + else { + /* + CString msg; + char *full_msg; + char short_msg[MAX_STRING_DISPLAY_LEN+1]; + + // Display the first X chars in message + full_msg=FindMessageInList(data->str_val); + if(full_msg!=NULL) { + if(strlen(full_msg) > MAX_STRING_DISPLAY_LEN) { + strncpy(short_msg,full_msg,MAX_STRING_DISPLAY_LEN); + short_msg[MAX_STRING_DISPLAY_LEN]='\0'; + msg=short_msg; + msg+="..."; + } + else + msg=full_msg; + } + else + msg=""; + + text.Format("%s=\"%s\"",data->str_val,msg); + */ + text.Format("%s",data->str_val); + } + break; + case PERCENTAGE_PARAMETER_TYPE: + text.Format("%.1f%%",data->float_val1*100.0); + break; + case ENUM_PARAMETER_TYPE: + if(data->subID==USE_GOALID_VALUE) { + text.Format("GOAL ID"); + } + else if(data->subID==USE_TIMERID_VALUE) { + text.Format("TIMER ID"); + } + else if(data->subID==USE_MATCENID_VALUE) { + text.Format("MATCEN ID"); + } + else { + temp_str=GetEnumValueName(data->name,data->int_val); + if(temp_str==NULL) + text.Format("*UNKNOWN_ENUM*"); + else + text.Format("%s",temp_str); + } + break; + case SCRIPT_PARAMETER_TYPE: + if(data->int_val == NOT_SPECIFIED_TYPE) { + text.Format("%s",NOT_SPECIFIED_STRING); + break; + } + text.Format("%d",data->int_val); + break; + case SOUND_PARAMETER_TYPE: + if(data->int_val == NOT_SPECIFIED_TYPE) { + text.Format("%s",NOT_SPECIFIED_STRING); + break; + } + if(data->int_val<0 || data->int_val>=MAX_SOUNDS || !Sounds[data->int_val].used) + text.Format("*INVALID_SOUND*"); + else + text.Format("%s",Sounds[data->int_val].name); + break; + case SPECNAME_PARAMETER_TYPE: + if(strlen(data->str_val)==0) + text.Format("%s",NOT_SPECIFIED_STRING); + else + text.Format("\"%s\"",data->str_val); + break; + case TEXTURE_PARAMETER_TYPE: + if(data->int_val == NOT_SPECIFIED_TYPE) { + text.Format("%s",NOT_SPECIFIED_STRING); + break; + } + if(data->int_val<0 || data->int_val>=MAX_TEXTURES || !GameTextures[data->int_val].used) + text.Format("*INVALID_TEXTURE*"); + else + text.Format("%s",GameTextures[data->int_val].name); + break; + case FLAG_PARAMETER_TYPE: + if(!FormatFlagValueNames(data->name,data->int_val,text)) + text.Format("*UNKNOWN_FLAG*"); + break; + case PATH_PARAMETER_TYPE: + if(data->int_val == NOT_SPECIFIED_TYPE) { + text.Format("%s",NOT_SPECIFIED_STRING); + break; + } + if(data->int_val<0 || data->int_val>=MAX_GAME_PATHS || !GamePaths[data->int_val].used) + text.Format("*INVALID_PATH*"); + else + text.Format("%s",GamePaths[data->int_val].name); + break; + case MATCEN_PARAMETER_TYPE: + if(data->subID==USE_MATCEN_EVENT_ID) { + text.Format("MATCEN ID"); + break; + } + if(data->int_val == NOT_SPECIFIED_TYPE) { + text.Format("%s",NOT_SPECIFIED_STRING); + break; + } + if(!MatcenValid(data->int_val)) + text.Format("*INVALID_MATCEN*"); + else { + char name[MAX_MATCEN_NAME_LEN+1]; + Matcen[data->int_val]->GetName(name); + text.Format("%s",name); + } + break; + case LEVEL_GOAL_PARAMETER_TYPE: + if(data->subID==USE_LEVEL_GOAL_ID) { + text.Format("LEVEL GOAL ID"); + break; + } + if(data->int_val == NOT_SPECIFIED_TYPE) { + text.Format("%s",NOT_SPECIFIED_STRING); + break; + } + if(Level_goals.GoalGetName(data->int_val,temp_name,MAX_PATH)<0) + text.Format("*INVALID_LEVEL_GOAL*"); + else { + text.Format("%s",temp_name); + } + break; + case STRM_AUDIO_PARAMETER_TYPE: + if(strlen(data->str_val)==0) + text.Format("%s",NOT_SPECIFIED_STRING); + else + text.Format("\"%s\"",data->str_val); + break; + default: + text.Format("Unknown Value Type"); + break; + } +} + + +// Parses an action desc, replacing arg blocks with value strings taken from +// its child parameter nodes +void CDallasMainDlg::FormatActionNodeText(CString &text, HTREEITEM action_node) +{ + CString name_text, default_text, range_text; + char *desc; + tTreeNodeData *data; + HTREEITEM child; + + if(action_node==NULL) { + text="*ERROR*"; + return; + } + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(action_node); + if(data==NULL) { + text="*ERROR*"; + return; + } + + if(data->ID==INVALID_FUNCTION_ID) { + text=INVALID_FUNCTION_NAME; + return; + } + + desc=GetActionDesc(data->ID); + if(desc==NULL) { + text="*ERROR*"; + return; + } + + // obtain the first child + child=m_ScriptTree.GetChildItem(action_node); + + text=""; + while((*desc)!='\0') { + if((*desc)=='[') { + ParseParamBlock(desc,name_text,default_text,range_text); + + if(child==NULL) + text+="???"; + else { + CString tmp_str; + tTreeNodeData *data; + + // Get node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(child); + + if(data->type==PARAMETER_NODE) { + FormatParameterValueText(tmp_str,data); + text+=tmp_str; + } + else if(data->type==EXPRESSION_NODE) { + FormatQueryNodeText(tmp_str,child); + text+="("; + text+=tmp_str; + text+=")"; + } + else + text+=""; + + // Get next child + child=m_ScriptTree.GetNextSiblingItem(child); + } + } + else { + text+=(*desc); + desc++; + } + } +} + +/* OLD VERSION +// Parses an action desc, replacing arg blocks with value strings taken from +// its child parameter nodes +void CDallasMainDlg::FormatActionNodeText(CString &text, HTREEITEM action_node) +{ + char *desc; + int j; + tTreeNodeData *data; + HTREEITEM child; + bool ok_to_copy; + + if(action_node==NULL) { + text="*ERROR*"; + return; + } + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(action_node); + if(data==NULL) { + text="*ERROR*"; + return; + } + + if(data->ID==INVALID_FUNCTION_ID) { + text=INVALID_FUNCTION_NAME; + return; + } + + desc=GetActionDesc(data->ID); + if(desc==NULL) { + text="*ERROR*"; + return; + } + + // obtain the first child + child=m_ScriptTree.GetChildItem(action_node); + + j=0; + ok_to_copy=TRUE; + text=""; + while(desc[j]!='\0') { + if(desc[j]=='[') { + ok_to_copy=FALSE; + } + else if(desc[j]==']') { + ok_to_copy=TRUE; + + if(child==NULL) + text+="???"; + else { + CString tmp_str; + tTreeNodeData *data; + + // Get node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(child); + + if(data->type==PARAMETER_NODE) { + FormatParameterValueText(tmp_str,data); + text+=tmp_str; + } + else if(data->type==EXPRESSION_NODE) { + FormatQueryNodeText(tmp_str,child); + text+="("; + text+=tmp_str; + text+=")"; + } + else + text+=""; + + // Get next child + child=m_ScriptTree.GetNextSiblingItem(child); + } + } + else if(ok_to_copy) { + text+=desc[j]; + } + + j++; + } +} +*/ + +// Parses a query desc, replacing arg blocks with value strings taken from +// its child parameter nodes +void CDallasMainDlg::FormatQueryNodeText(CString &text, HTREEITEM query_node) +{ + CString name_text, default_text, range_text; + char *desc; + HTREEITEM child; + tTreeNodeData *data; + + if(query_node==NULL) { + text="*ERROR*"; + return; + } + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(query_node); + if(data==NULL) { + text="*ERROR*"; + return; + } + + if(data->ID==INVALID_FUNCTION_ID) { + text=INVALID_FUNCTION_NAME; + return; + } + + desc=GetQueryDesc(data->ID); + if(desc==NULL) { + text="*ERROR*"; + return; + } + + // obtain the first child + child=m_ScriptTree.GetChildItem(query_node); + + text=""; + + // Skip over the return type + desc=strchr(desc,':'); + if(desc==NULL) return; + desc++; + + while((*desc)!='\0') { + if((*desc)=='[') { + ParseParamBlock(desc,name_text,default_text,range_text); + + if(child==NULL) + text+="???"; + else { + CString tmp_str; + tTreeNodeData *data; + + // Get node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(child); + + if(data->type==PARAMETER_NODE) { + FormatParameterValueText(tmp_str,data); + text+=tmp_str; + } + else if(data->type==EXPRESSION_NODE) { + CString tmp_str; + FormatQueryNodeText(tmp_str,child); + text+="("; + text+=tmp_str; + text+=")"; + } + else + text+=""; + + // Get next child + child=m_ScriptTree.GetNextSiblingItem(child); + } + } + else { + text+=(*desc); + desc++; + } + } +} + +/* OLD VERSION +// Parses a query desc, replacing arg blocks with value strings taken from +// its child parameter nodes +void CDallasMainDlg::FormatQueryNodeText(CString &text, HTREEITEM query_node) +{ + char *desc; + int j; + HTREEITEM child; + tTreeNodeData *data; + bool ok_to_copy, first_colon_found; + + if(query_node==NULL) { + text="*ERROR*"; + return; + } + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(query_node); + if(data==NULL) { + text="*ERROR*"; + return; + } + + if(data->ID==INVALID_FUNCTION_ID) { + text=INVALID_FUNCTION_NAME; + return; + } + + desc=GetQueryDesc(data->ID); + if(desc==NULL) { + text="*ERROR*"; + return; + } + + // obtain the first child + child=m_ScriptTree.GetChildItem(query_node); + + j=0; + ok_to_copy=FALSE; + first_colon_found=FALSE; + text=""; + while(desc[j]!='\0') { + if(desc[j]=='[') { + ok_to_copy=FALSE; + } + else if(desc[j]==']') { + ok_to_copy=TRUE; + + if(child==NULL) + text+="???"; + else { + CString tmp_str; + tTreeNodeData *data; + + // Get node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(child); + + if(data->type==PARAMETER_NODE) { + FormatParameterValueText(tmp_str,data); + text+=tmp_str; + } + else if(data->type==EXPRESSION_NODE) { + CString tmp_str; + FormatQueryNodeText(tmp_str,child); + text+="("; + text+=tmp_str; + text+=")"; + } + else + text+=""; + + // Get next child + child=m_ScriptTree.GetNextSiblingItem(child); + } + } + else if(desc[j]==':' && !first_colon_found) { + first_colon_found=TRUE; + ok_to_copy=TRUE; + } + else if(ok_to_copy) { + text+=desc[j]; + } + + j++; + } +} +*/ + +// Converts a parameter character ID into a paramter type +int CDallasMainDlg::ConvertParamCharToType(int param_char_ID) +{ + int param_type; + + switch(param_char_ID) { + case 'd': param_type=DOOR_PARAMETER_TYPE; break; + case 'o': param_type=OBJECT_PARAMETER_TYPE; break; + case 'r': param_type=ROOM_PARAMETER_TYPE; break; + case 't': param_type=TRIGGER_PARAMETER_TYPE; break; + case 'i': param_type=INT_PARAMETER_TYPE; break; + case 'b': param_type=BOOL_PARAMETER_TYPE; break; + case 'f': param_type=FLOAT_PARAMETER_TYPE; break; + case 'v': param_type=VECTOR_PARAMETER_TYPE; break; + case 's': param_type=STRING_PARAMETER_TYPE; break; + case 'p': param_type=PERCENTAGE_PARAMETER_TYPE; break; + case 'e': param_type=ENUM_PARAMETER_TYPE; break; + case 'x': param_type=SCRIPT_PARAMETER_TYPE; break; + case 'n': param_type=SOUND_PARAMETER_TYPE; break; + case 'a': param_type=SPECNAME_PARAMETER_TYPE; break; + case 'u': param_type=TEXTURE_PARAMETER_TYPE; break; + case 'g': param_type=FLAG_PARAMETER_TYPE; break; + case 'h': param_type=PATH_PARAMETER_TYPE; break; + case 'm': param_type=MATCEN_PARAMETER_TYPE; break; + case 'l': param_type=LEVEL_GOAL_PARAMETER_TYPE; break; + case 'z': param_type=STRM_AUDIO_PARAMETER_TYPE; break; + default: param_type=UNKNOWN_PARAMETER_TYPE; break; + } + + return(param_type); +} + + +// Converts a parameter type into a character ID +int CDallasMainDlg::ConvertParamTypeToChar(int param_type) +{ + int param_char_ID; + + switch(param_type) { + case DOOR_PARAMETER_TYPE: param_char_ID='d'; break; + case OBJECT_PARAMETER_TYPE: param_char_ID='o'; break; + case ROOM_PARAMETER_TYPE: param_char_ID='r'; break; + case TRIGGER_PARAMETER_TYPE: param_char_ID='t'; break; + case INT_PARAMETER_TYPE: param_char_ID='i'; break; + case BOOL_PARAMETER_TYPE: param_char_ID='b'; break; + case FLOAT_PARAMETER_TYPE: param_char_ID='f'; break; + case VECTOR_PARAMETER_TYPE: param_char_ID='v'; break; + case STRING_PARAMETER_TYPE: param_char_ID='s'; break; + case PERCENTAGE_PARAMETER_TYPE: param_char_ID='p'; break; + case ENUM_PARAMETER_TYPE: param_char_ID='e'; break; + case SCRIPT_PARAMETER_TYPE: param_char_ID='x'; break; + case SOUND_PARAMETER_TYPE: param_char_ID='n'; break; + case SPECNAME_PARAMETER_TYPE: param_char_ID='a'; break; + case TEXTURE_PARAMETER_TYPE: param_char_ID='u'; break; + case FLAG_PARAMETER_TYPE: param_char_ID='g'; break; + case PATH_PARAMETER_TYPE: param_char_ID='h'; break; + case MATCEN_PARAMETER_TYPE: param_char_ID='m'; break; + case LEVEL_GOAL_PARAMETER_TYPE: param_char_ID='l'; break; + case STRM_AUDIO_PARAMETER_TYPE: param_char_ID='z'; break; + default: param_char_ID='?'; break; + } + + return(param_char_ID); +} + + +// Turns bold on or off for a specified node +void CDallasMainDlg::SetBoldNodeText(HTREEITEM node, bool bold_on) +{ + if(node==NULL) return; + + if(bold_on) + m_ScriptTree.SetItemState(node,TVIS_BOLD,TVIS_BOLD); + else + m_ScriptTree.SetItemState(node,~TVIS_BOLD,TVIS_BOLD); +} + + +// Checks to see if the parent of the given node is a Conditional Statement +// node of type COMPARISON_STATEMENT +bool CDallasMainDlg::ParentIsComparisonConditional(HTREEITEM node) +{ + HTREEITEM parent; + tTreeNodeData *data; + + if(node==NULL) return(FALSE); + + // Get the parent + parent=m_ScriptTree.GetParentItem(node); + if(parent==NULL) return(FALSE); + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(parent); + if(data==NULL) return(FALSE); + + // Check the parent node + if(data->type==CONDITIONAL_STATEMENT_NODE && data->ID==COMPARISON_STATEMENT) + return(TRUE); + + return(FALSE); +} + + +// If the given node is a parameter or query, it determines its type (or return type) +// and returns it, unless the parent of the given node is a Comparison conditional +// statement. In this case, any parameter type is allowed +int CDallasMainDlg::GetValidParamType(HTREEITEM node, CString &name) +{ + tTreeNodeData *data; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); + if(data==NULL) return(-1); + + name=""; + + if(data->type==PARAMETER_NODE) { + if(ParentIsComparisonConditional(node) && GetChildPosition(node)==1) + return(ANY_PARAMETER_TYPE); + name=data->name; + return(data->ID); + } + + if(data->type==EXPRESSION_NODE) { + if(ParentIsComparisonConditional(node) && GetChildPosition(node)==1) + return(ANY_PARAMETER_TYPE); + return(GetQueryReturnType(data->ID,name)); + } + + return(-1); +} + + +// If the given node is a parameter or query, it determines its type (or return type) +// and returns it +int CDallasMainDlg::GetParamType(HTREEITEM node, CString &name) +{ + tTreeNodeData *data; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); + if(data==NULL) return(-1); + + name=""; + + if(data->type==PARAMETER_NODE) { + name=data->name; + return(data->ID); + } + + if(data->type==EXPRESSION_NODE) { + return(GetQueryReturnType(data->ID,name)); + } + + return(-1); +} + + +// Attaches the correct bitmap image to a node +void CDallasMainDlg::SetTreeNodeImage(HTREEITEM node) +{ + tTreeNodeData *data; + int temp_id; + + // Make sure node is valid + if(node==NULL) return; + + // Get node data, make sure it's valid + data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); + if(data==NULL) return; + + // Set the item's display images appropriately + switch(data->type) { + case SCRIPT_HEADER_NODE: + m_ScriptTree.SetItemImage(node,0,0); + break; + case SCRIPT_OWNER_NODE: + m_ScriptTree.SetItemImage(node,10,10); + break; + case SCRIPT_EVENT_NODE: + m_ScriptTree.SetItemImage(node,11,11); + break; + case CONDITIONAL_HEADER_NODE: + if(data->ID==TOP_LEVEL) + m_ScriptTree.SetItemImage(node,1,1); + else + m_ScriptTree.SetItemImage(node,8,8); + break; + case ACTIONS_HEADER_NODE: + if(data->ID==TOP_LEVEL) + m_ScriptTree.SetItemImage(node,2,2); + else { + if(data->subID==THEN_CLAUSE) + m_ScriptTree.SetItemImage(node,9,9); + else + m_ScriptTree.SetItemImage(node,18,18); + } + break; + case CONDITIONAL_STATEMENT_NODE: + m_ScriptTree.SetItemImage(node,3,3); + break; + case EXPRESSION_NODE: + m_ScriptTree.SetItemImage(node,16,16); + break; + case EXPRESSION_OPERATOR_NODE: + m_ScriptTree.SetItemImage(node,17,17); + break; + case ACTION_STATEMENT_NODE: + m_ScriptTree.SetItemImage(node,4,4); + break; + case LOGICAL_OPERATOR_NODE: + if(data->ID==AND_TYPE) + m_ScriptTree.SetItemImage(node,6,6); + else if(data->ID==OR_TYPE) + m_ScriptTree.SetItemImage(node,5,5); + else + m_ScriptTree.SetItemImage(node,7,7); + break; + case PARAMETER_NODE: + // Get image type based upon what kind of parameter it is + switch(data->ID) { + case DOOR_PARAMETER_TYPE: temp_id=12; break; + case OBJECT_PARAMETER_TYPE: temp_id=12; break; + case ROOM_PARAMETER_TYPE: temp_id=12; break; + case TRIGGER_PARAMETER_TYPE: temp_id=12; break; + case INT_PARAMETER_TYPE: temp_id=13; break; + case BOOL_PARAMETER_TYPE: temp_id=14; break; + case FLOAT_PARAMETER_TYPE: temp_id=13; break; + case VECTOR_PARAMETER_TYPE: temp_id=15; break; + case STRING_PARAMETER_TYPE: temp_id=12; break; + case PERCENTAGE_PARAMETER_TYPE: temp_id=14; break; + case ENUM_PARAMETER_TYPE: temp_id=12; break; + case SCRIPT_PARAMETER_TYPE: temp_id=12; break; + case SOUND_PARAMETER_TYPE: temp_id=15; break; + case SPECNAME_PARAMETER_TYPE: temp_id=13; break; + case TEXTURE_PARAMETER_TYPE: temp_id=15; break; + case FLAG_PARAMETER_TYPE: temp_id=15; break; + case PATH_PARAMETER_TYPE: temp_id=12; break; + case MATCEN_PARAMETER_TYPE: temp_id=12; break; + case LEVEL_GOAL_PARAMETER_TYPE: temp_id=12; break; + case STRM_AUDIO_PARAMETER_TYPE: temp_id=15; break; + default: temp_id=12; break; + } + m_ScriptTree.SetItemImage(node,temp_id,temp_id); + break; + case PARAMETER_OPERATOR_NODE: + m_ScriptTree.SetItemImage(node,13,13); + break; + case CLIPBOARD_HEADER_NODE: + m_ScriptTree.SetItemImage(node,19,19); + break; + case UNKNOWN_NODE: + m_ScriptTree.SetItemImage(node,0,0); + break; + default: + m_ScriptTree.SetItemImage(node,0,0); + break; + } +} + + +// Adds a node to the tree using the given data +HTREEITEM CDallasMainDlg::AddNodeToTree(HTREEITEM parent, HTREEITEM insertbefore, HTREEITEM src_node, bool expand /*=FALSE*/) +{ + tTreeNodeData *data; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(src_node); + return(AddNodeToTree(parent,insertbefore,data,expand)); +} + + +// Adds a node to the tree using the given data +HTREEITEM CDallasMainDlg::AddNodeToTree(HTREEITEM parent, HTREEITEM insertbefore, tTreeNodeData *data_node, bool expand /*=FALSE*/) +{ + HTREEITEM added_item, insertafter, new_parent; + TV_INSERTSTRUCT tvs; + TV_ITEM tvi; + tTreeNodeData *new_data_node; + CString node_text; + + // Allocate a new data node, and copy given data into it + new_data_node=new tTreeNodeData; + if(new_data_node==NULL) { + MessageBox("Unable to Allocate a New Data Node","Out of Memory Error!",MB_OK|MB_ICONEXCLAMATION); + return NULL; + } + + // Copy given data into new node + (*new_data_node)=(*data_node); + + // Fill out the Item structure + tvi.mask=TVIF_TEXT; + //FormatTreeText(node_text,new_data_node); + //tvi.pszText=node_text.GetBuffer(0); + tvi.pszText=""; + + // Get the previous child node for "insert before" + if(insertbefore!=TVI_FIRST && insertbefore!=TVI_LAST && insertbefore!=TVI_SORT) { + insertafter=m_ScriptTree.GetPrevSiblingItem(insertbefore); + if(insertafter==NULL) insertafter=TVI_FIRST; + new_parent=parent; + } + else { + insertafter=insertbefore; + new_parent=parent; + } + + // Fill out the Insert structure + tvs.hInsertAfter=insertafter; + tvs.hParent=new_parent; + tvs.item=tvi; + + added_item=m_ScriptTree.InsertItem(&tvs); + + // If add was unsuccessfull, delete the item data + if(added_item==NULL) { + delete new_data_node; + MessageBox("Unable to Allocate a New Tree Node","Out of Memory Error!",MB_OK|MB_ICONEXCLAMATION); + return NULL; + } + + // Set the node data and image + m_ScriptTree.SetItemData(added_item,(DWORD)new_data_node); + SetTreeNodeImage(added_item); + + // Set the new node's text + UpdateNodeText(added_item); + + // Expand the parent if necessary + if(parent!=NULL && expand) + m_ScriptTree.Expand(parent,TVE_EXPAND); + + return(added_item); +} + + +// Frees all data for a tree leaf (and all children of the given leaf) +void CDallasMainDlg::FreeTreeItem(HTREEITEM item) +{ + tTreeNodeData *data; + + if (item==NULL) return; + + // Free all children of this node + FreeTreeItemChildren(item); + + // Deallocate the data structure + data=(tTreeNodeData *)m_ScriptTree.GetItemData(item); + delete data; + + // Delete the actual tree node + m_ScriptTree.DeleteItem(item); +} + + +// Frees all children of the given leaf, but leaves the given leaf intact +void CDallasMainDlg::FreeTreeItemChildren(HTREEITEM item) +{ + HTREEITEM child, old_child; + + if (item==NULL) return; + + child = m_ScriptTree.GetChildItem(item); + while (child) + { + old_child = child; + child = m_ScriptTree.GetNextSiblingItem(child); + FreeTreeItem(old_child); + } +} + + +// Expands given node and all children +void CDallasMainDlg::ExpandAll(HTREEITEM node, UINT nCode) +{ + HTREEITEM child; + + if (node==NULL) return; + + child = m_ScriptTree.GetChildItem(node); + while (child!=NULL) + { + ExpandAll(child,nCode); + child = m_ScriptTree.GetNextSiblingItem(child); + } + + // Expand this node + m_ScriptTree.Expand(node,nCode); +} + + +// Copies the entire tree starting at src_node to the specified destination +HTREEITEM CDallasMainDlg::CopyTree(HTREEITEM dest_parent, HTREEITEM dest_insert_before, HTREEITEM src_node) +{ + HTREEITEM dest_node; + + dest_node=AddNodeToTree(dest_parent,dest_insert_before,src_node); + if(dest_node!=NULL) { + CopyChildren(dest_node,src_node); + UpdateNodeText(dest_node); + } + + return(dest_node); +} + + +// Copies all the children of src_parent to dest_parent +HTREEITEM CDallasMainDlg::CopyChildren(HTREEITEM dest_parent, HTREEITEM src_parent) +{ + HTREEITEM src_child, dest_child; + + dest_child=NULL; + src_child=m_ScriptTree.GetChildItem(src_parent); + while(src_child!=NULL) { + dest_child=AddNodeToTree(dest_parent,TVI_LAST,src_child); + if(dest_child==NULL) return NULL; + CopyChildren(dest_child,src_child); + UpdateNodeText(dest_child); + src_child=m_ScriptTree.GetNextSiblingItem(src_child); + } + + return(dest_child); +} + + +// Returns the position of the given child (i.e. child is the Nth child of parent) +int CDallasMainDlg::GetChildPosition(HTREEITEM child) +{ + HTREEITEM node; + int count; + + if(child==NULL) return 0; + + count=1; + node=m_ScriptTree.GetPrevSiblingItem(child); + while(node!=NULL) { + node=m_ScriptTree.GetPrevSiblingItem(node); + count++; + } + + return(count); +} + + +// Returns the Nth child of the given parent (NULL if one doesn't exist) +HTREEITEM CDallasMainDlg::GetNthChild(HTREEITEM parent, int n) +{ + HTREEITEM child; + int count; + + if(parent==NULL || n<=0) return NULL; + + count=1; + child=m_ScriptTree.GetChildItem(parent); + + while(child!=NULL && count!=n) { + child=m_ScriptTree.GetNextSiblingItem(child); + count++; + } + + return(child); +} + + +// Returns the child count +int CDallasMainDlg::GetChildCount(HTREEITEM parent) +{ + HTREEITEM child; + int count; + + if(parent==NULL) return 0; + + count=0; + child=m_ScriptTree.GetChildItem(parent); + while(child!=NULL) { + child=m_ScriptTree.GetNextSiblingItem(child); + count++; + } + + return(count); +} + + +// Returns the script ID for any given node (must be a descendant of SCRIPT_HEADER_NODE though) +int CDallasMainDlg::GetScriptID(HTREEITEM script_node) +{ + HTREEITEM script_header_node; + tTreeNodeData *data; + + script_header_node=GetParentNodeOfType(script_node,SCRIPT_HEADER_NODE); + if(script_header_node==NULL) return(-1); + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_header_node); + if(data==NULL) return(-1); + + return(data->ID); +} + + +// Returns script header node of script matching given script ID (NULL if not found) +HTREEITEM CDallasMainDlg::FindScriptIDNode(int scriptID) +{ + HTREEITEM node; + + // Fill up the list + node=m_ScriptTree.GetChildItem(TVI_ROOT); + while(node!=NULL) { + int id=GetScriptID(node); + if(id==scriptID) { + return(node); + } + node=m_ScriptTree.GetNextSiblingItem(node); + } + + return(NULL); +} + + +// Compare function for GetLowestUnusedScriptID() +int id_list_compare( const void *arg1, const void *arg2 ) +{ + int *num1=(int *)arg1; + int *num2=(int *)arg2; + + if((*num1) < (*num2)) return(-1); + return (1); +} + +// Looks through scripts to determine the lowest unused script ID +int CDallasMainDlg::GetLowestUnusedScriptID(void) +{ + int *list; + int size; + int max_size; + int lowest_id; + HTREEITEM node; + + lowest_id=0; + + // Create the Script ID List + max_size=GetChildCount(TVI_ROOT); + if(max_size==0) return(lowest_id); + list=(int *)mem_malloc(sizeof(int)*max_size); + if(list==NULL) return(m_NextScriptID); + + // Fill up the list + size=0; + node=m_ScriptTree.GetChildItem(TVI_ROOT); + while(node!=NULL) { + int id=GetScriptID(node); + if(id>=0 && size %d ",lowest_id); + msg+=num; + MessageBox(msg,"The Script ID List"); + */ + + // Free up the list + mem_free(list); + + return(lowest_id); +} + + +// Returns the node type of given node +int CDallasMainDlg::GetNodeType(HTREEITEM node) +{ + tTreeNodeData *data; + + if(node==NULL) return(UNKNOWN_NODE); + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); + if(data==NULL) return(UNKNOWN_NODE); + + return(data->type); +} + + +// Returns the script owner type for any given node (must be a descendant of SCRIPT_HEADER_NODE though) +int CDallasMainDlg::GetScriptOwnerType(HTREEITEM script_node) +{ + HTREEITEM script_owner_node; + tTreeNodeData *data; + + script_owner_node=GetScriptOwnerNode(script_node); + if(script_owner_node==NULL) return(-1); + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_owner_node); + if(data==NULL) return(-1); + + return(data->ID); +} + + +// Returns the script event type for any given node (must be a descendant of SCRIPT_HEADER_NODE though) +int CDallasMainDlg::GetScriptEventType(HTREEITEM script_node) +{ + HTREEITEM script_event_node; + tTreeNodeData *data; + + script_event_node=GetScriptEventNode(script_node); + if(script_event_node==NULL) return(-1); + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_event_node); + if(data==NULL) return(-1); + + return(data->ID); +} + + +// Sets the script event type for any given node (must be a descendant of SCRIPT_HEADER_NODE though) +bool CDallasMainDlg::SetScriptEventType(HTREEITEM script_node, int type) +{ + HTREEITEM script_event_node; + tTreeNodeData *data; + + script_event_node=GetScriptEventNode(script_node); + if(script_event_node==NULL) return FALSE; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_event_node); + if(data==NULL) return FALSE; + + data->ID=type; + UpdateAllParentNodesText(script_event_node); + + return TRUE; +} + + +// Searches for a parent node (or current node) that matches the given type (returns NULL if none found) +HTREEITEM CDallasMainDlg::GetParentNodeOfType(HTREEITEM child_node, int node_type) +{ + HTREEITEM parent; + tTreeNodeData *data; + + parent=child_node; + while(parent!=NULL) { + data=(tTreeNodeData *)m_ScriptTree.GetItemData(parent); + if(data!=NULL && data->type==node_type) + return(parent); + parent=m_ScriptTree.GetParentItem(parent); + } + + return(parent); +} + + +// Returns the data of the closest EXPRESSION or ACTION node to the given node +tTreeNodeData *CDallasMainDlg::GetNearestFunctionNode(HTREEITEM node) +{ + HTREEITEM parent; + tTreeNodeData *data; + + parent=node; + while(parent!=NULL) { + data=(tTreeNodeData *)m_ScriptTree.GetItemData(parent); + if(data!=NULL && (data->type==EXPRESSION_NODE || data->type==ACTION_STATEMENT_NODE)) + return(data); + parent=m_ScriptTree.GetParentItem(parent); + } + + return(NULL); +} + + +// Searches for either an ACTION_STATEMENT_NODE or an EXPRESSION_NODE +// that is the closest parent to the given PARAMETER_NODE (returns NULL if none found) +HTREEITEM CDallasMainDlg::GetParameterParentNode(HTREEITEM param_node) +{ + HTREEITEM parent; + tTreeNodeData *data; + + // Make sure given node is a parameter node + data=(tTreeNodeData *)m_ScriptTree.GetItemData(param_node); + if(data==NULL || data->type!=PARAMETER_NODE) return NULL; + + // Keep getting the parent until we find a good match (or run out of parents) + parent=m_ScriptTree.GetParentItem(param_node); + while(parent!=NULL) { + data=(tTreeNodeData *)m_ScriptTree.GetItemData(parent); + if(data!=NULL && data->type==ACTION_STATEMENT_NODE) + return(parent); + if(data!=NULL && data->type==EXPRESSION_NODE) + return(parent); + parent=m_ScriptTree.GetParentItem(parent); + } + + return(parent); +} + + +// Returns the owner node for any given Script node +HTREEITEM CDallasMainDlg::GetScriptOwnerNode(HTREEITEM node) +{ + HTREEITEM temp_node; + + // Get the parent Script header node of the given node + temp_node=GetParentNodeOfType(node,SCRIPT_HEADER_NODE); + if(temp_node==NULL) return NULL; + + // Get the owner node (first child of script header) + temp_node=m_ScriptTree.GetChildItem(temp_node); + + return(temp_node); +} + + +// Returns the event node for any given Script node +HTREEITEM CDallasMainDlg::GetScriptEventNode(HTREEITEM node) +{ + HTREEITEM temp_node; + + // Get the script owner node + temp_node=GetScriptOwnerNode(node); + if(node==NULL) return NULL; + + // Get the event node (next node after owner) + temp_node=m_ScriptTree.GetNextSiblingItem(temp_node); + + return(temp_node); +} + + +// Returns the conditional header (TOP LEVEL) node for any given Script node +HTREEITEM CDallasMainDlg::GetConditionalHeaderNode(HTREEITEM node) +{ + HTREEITEM temp_node; + + // Get the script owner node + temp_node=GetScriptEventNode(node); + if(node==NULL) return NULL; + + // Get the conditional header node (next node after event node) + temp_node=m_ScriptTree.GetNextSiblingItem(temp_node); + + return(temp_node); +} + + +// Returns the action header (TOP LEVEL) node for any given Script node +HTREEITEM CDallasMainDlg::GetActionHeaderNode(HTREEITEM node) +{ + HTREEITEM temp_node; + + // Get the script owner node + temp_node=GetConditionalHeaderNode(node); + if(node==NULL) return NULL; + + // Get the action header node (next node after conditional header) + temp_node=m_ScriptTree.GetNextSiblingItem(temp_node); + + return(temp_node); +} + + +// Highlights the headers for all scripts whose owner matches +// the owner specified in m_ScriptOwnerType and m_ScriptOwnerHandle +void CDallasMainDlg::HighlightAllScripts(void) +{ + HTREEITEM script_header_node; + + // Group each script header node into the list + script_header_node=m_ScriptTree.GetChildItem(TVI_ROOT); + while(script_header_node!=NULL) { + HighlightScript(script_header_node); + script_header_node=m_ScriptTree.GetNextSiblingItem(script_header_node); + } +} + + +// Highlights the headers for all scripts whose owner matches +// the owner specified in m_ScriptOwnerType and m_ScriptOwnerHandle +void CDallasMainDlg::HighlightScript(HTREEITEM node) +{ + HTREEITEM script_header_node; + + script_header_node=GetParentNodeOfType(node,SCRIPT_HEADER_NODE); + if(script_header_node==NULL) return; + + HTREEITEM owner_node, event_node; + tTreeNodeData *data; + bool owners_match; + + owners_match=FALSE; + owner_node=GetScriptOwnerNode(script_header_node); + if(owner_node!=NULL) { + data=(tTreeNodeData *)m_ScriptTree.GetItemData(owner_node); + if(data!=NULL) { + if(m_ScriptOwnerType==ALL_OWNERS_TYPE) + owners_match=TRUE; + else if(m_ScriptOwnerType==LEVEL_TYPE && data->ID==LEVEL_TYPE) + owners_match=TRUE; + else if(m_ScriptOwnerType==ALL_OBJECTS_TYPE && data->ID==OBJECT_TYPE) + owners_match=TRUE; + else if(m_ScriptOwnerType==ALL_TRIGGERS_TYPE && data->ID==TRIGGER_TYPE) + owners_match=TRUE; + else if(m_ScriptOwnerType==data->ID && m_ScriptOwnerHandle==data->int_val) + owners_match=TRUE; + } + } + + event_node=GetScriptEventNode(script_header_node); + if(event_node!=NULL) { + data=(tTreeNodeData *)m_ScriptTree.GetItemData(event_node); + if(data!=NULL) { + int event_type=GetHighlightedEvent(); + if(event_type!=ALL_EVENT_TYPES && data->ID!=event_type) + owners_match=FALSE; + } + } + + if(owners_match) + SetBoldNodeText(script_header_node,TRUE); + else + SetBoldNodeText(script_header_node,FALSE); +} + + +///////////////////////////////////////////////////////////////////////////// +// Message List Functions +///////////////////////////////////////////////////////////////////////////// + +// Initializes the message list, +// MUST BE CALLED BEFORE USING ANY MESSAGE LIST functions!!! +void CDallasMainDlg::InitMessageList(void) +{ + int j; + + // Init the list of message entries to empty + for(j=0;jname,name,MAX_MESSAGE_NAME_LEN); + empty_slot->name[MAX_MESSAGE_NAME_LEN]='\0'; + strncpy(empty_slot->message,message,MAX_MESSAGE_LEN); + empty_slot->message[MAX_MESSAGE_LEN]='\0'; + + // Add to the list and edit controls + index=m_MessageList.AddString(name); + if(index<0) { + m_MessageListErrorCode=MSG_LIST_FULL_ERROR; + return FALSE; + } + + m_MessageList.SetItemData(index,(DWORD)empty_slot); + + // Set the new selection to be the current selection + m_MessageList.SetCurSel(index); + OnSelchangeMessageList(); + + return TRUE; +} + +// Returns a message matching the given name, or NULL if none found +char *CDallasMainDlg::FindMessageInList(char *name) +{ + int j; + + // Scan entry list for given name + for(j=0;jname,name)==0) + return(m_MessageEntryList[j]->message); + + return(NULL); +} + +// Deletes a message entry +int CDallasMainDlg::DeleteMessageListEntry(char *name) +{ + int j; + + // Scan entry list for given name + for(j=0;jname,name)==0) { + delete m_MessageEntryList[j]; + m_MessageEntryList[j]=NULL; + return(TRUE); + } + + return(FALSE); +} + +// Returns an available entry slot, or NULL if none exist +tMessageListEntry *CDallasMainDlg::GetEmptyMessageListEntry(void) +{ + int j; + + // Scan entry list for an empty slot + for(j=0;jtype==SCRIPT_OWNER_NODE) { + if(data->ID==NOT_SPECIFIED_TYPE) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Script Owner"); + return 1; + } + if(data->ID==LEVEL_TYPE) return 0; + if(data->ID==OBJECT_TYPE) { + // Check for object None + if(data->int_val == OBJECT_HANDLE_NONE) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Script Owner (Object)"); + return 1; + } + + // Check for invalid objects + object *objp=ObjGet(data->int_val); + if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { + int handle=osipf_FindObjectName(data->str_val); + if(handle!=OBJECT_HANDLE_NONE) { + if(InvObjPrompt(scriptID,data->int_val,data->str_val,handle)==IDYES) { + data->int_val=handle; + UpdateAllParentNodesText(node); + AddObjectToList(data->str_val); + return 0; + } + } + InvObjMsg(scriptID,data->int_val,data->str_val); + data->int_val=OBJECT_HANDLE_NONE; + strcpy(data->str_val,""); + UpdateAllParentNodesText(node); + return 1; + } + + // Check for invalid object names + if(strcmp(data->str_val,objp->name)!=0) { + int handle=osipf_FindObjectName(data->str_val); + if(handle!=OBJECT_HANDLE_NONE) { + if(InvNameObjPrompt(scriptID,data->int_val,data->str_val,objp->name,handle)==IDYES) { + data->int_val=handle; + UpdateAllParentNodesText(node); + AddObjectToList(data->str_val); + return 0; + } + } + InvNameObjMsg(scriptID,data->int_val,data->str_val,objp->name); + strcpy(data->str_val,objp->name); + UpdateAllParentNodesText(node); + AddObjectToList(data->str_val); + return 0; + } + + // All is cool, so just add the name + AddObjectToList(objp->name); + return 0; + } + if(data->ID==TRIGGER_TYPE) { + // Check for not specified triggers + if(data->int_val == NOT_SPECIFIED_TYPE) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Script Owner (Trigger)"); + return 1; + } + + // Check for invalid triggers + int t=data->int_val; + if(t<0 || t>=Num_triggers || t>=MAX_NAMED_TRIGGERS || strlen(Triggers[t].name)==0) { + int index=osipf_FindTriggerName(data->str_val); + if(index>=0) { + if(InvIndValPrompt(scriptID,"Trigger",t,data->str_val,index)==IDYES) { + data->int_val=index; + UpdateAllParentNodesText(node); + AddTriggerToList(data->str_val); + return 0; + } + } + InvIndValMsg(scriptID,"Trigger",t,data->str_val); + data->int_val=NOT_SPECIFIED_TYPE; + strcpy(data->str_val,""); + UpdateAllParentNodesText(node); + return 1; + } + + // Check for invalid trigger names + if(strcmp(data->str_val,Triggers[t].name)!=0) { + int index=osipf_FindTriggerName(data->str_val); + if(index>=0) { + if(InvNameIndValPrompt(scriptID,"Trigger",t,data->str_val,Triggers[t].name,index)==IDYES) { + data->int_val=index; + UpdateAllParentNodesText(node); + AddTriggerToList(data->str_val); + return 0; + } + } + InvNameIndValMsg(scriptID,"Trigger",t,data->str_val,Triggers[t].name); + strcpy(data->str_val,Triggers[t].name); + UpdateAllParentNodesText(node); + AddTriggerToList(data->str_val); + return 0; + } + + // All is cool, so just add the name + AddTriggerToList(Triggers[t].name); + return 0; + } + } + + // See if it's a parameter Node + if(data->type==PARAMETER_NODE) { + switch(data->ID) { + case DOOR_PARAMETER_TYPE: + { + // Check for ME handle + if(data->subID==USE_ME_HANDLE) { + if(ScriptHasADoorMe(node)) { + return 0; + } + else { + InvSpecParamMsg(scriptID,"an OWNER (Door object)"); + return 1; + } + } + + // Check for IT handle + if(data->subID==USE_IT_HANDLE) return 0; + + // Check for object None + if(data->int_val == OBJECT_HANDLE_NONE) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Door Object"); + return 1; + } + + // Check for invalid door objects + object *objp=ObjGet(data->int_val); + if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { + int handle=osipf_FindDoorName(data->str_val); + if(handle!=OBJECT_HANDLE_NONE) { + if(InvObjPrompt(scriptID,data->int_val,data->str_val,handle)==IDYES) { + data->int_val=handle; + UpdateAllParentNodesText(node); + AddObjectToList(data->str_val); + return 0; + } + } + InvObjMsg(scriptID,data->int_val,data->str_val); + data->int_val=OBJECT_HANDLE_NONE; + strcpy(data->str_val,""); + UpdateAllParentNodesText(node); + return 1; + } + + // Check for invalid door object names + if(strcmp(data->str_val,objp->name)!=0) { + int handle=osipf_FindDoorName(data->str_val); + if(handle!=OBJECT_HANDLE_NONE) { + if(InvNameObjPrompt(scriptID,data->int_val,data->str_val,objp->name,handle)==IDYES) { + data->int_val=handle; + UpdateAllParentNodesText(node); + AddObjectToList(data->str_val); + return 0; + } + } + InvNameObjMsg(scriptID,data->int_val,data->str_val,objp->name); + strcpy(data->str_val,objp->name); + UpdateAllParentNodesText(node); + AddObjectToList(data->str_val); + return 0; + } + + // All is cool, so just add the name + AddDoorToList(objp->name); + } + break; + case OBJECT_PARAMETER_TYPE: + { + // Check for ME and IT handles + if(data->subID==USE_ME_HANDLE) { + if(ScriptHasAMe(node)) { + return 0; + } + else { + InvSpecParamMsg(scriptID,"an OWNER (object)"); + return 1; + } + } + + if(data->subID==USE_IT_HANDLE) { + if(ScriptHasAnIt(node)) { + return 0; + } + else { + InvSpecParamMsg(scriptID,"an IT (object)"); + return 1; + } + } + + // Check for object None + if(data->int_val == OBJECT_HANDLE_NONE) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Generic Object"); + return 1; + } + + // Check for invalid objects + object *objp=ObjGet(data->int_val); + if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { + int handle=osipf_FindObjectName(data->str_val); + if(handle!=OBJECT_HANDLE_NONE) { + if(InvObjPrompt(scriptID,data->int_val,data->str_val,handle)==IDYES) { + data->int_val=handle; + UpdateAllParentNodesText(node); + AddObjectToList(data->str_val); + return 0; + } + } + InvObjMsg(scriptID,data->int_val,data->str_val); + data->int_val=OBJECT_HANDLE_NONE; + strcpy(data->str_val,""); + UpdateAllParentNodesText(node); + return 1; + } + + // Check for invalid object names + if(strcmp(data->str_val,objp->name)!=0) { + int handle=osipf_FindObjectName(data->str_val); + if(handle!=OBJECT_HANDLE_NONE) { + if(InvNameObjPrompt(scriptID,data->int_val,data->str_val,objp->name,handle)==IDYES) { + data->int_val=handle; + UpdateAllParentNodesText(node); + AddObjectToList(data->str_val); + return 0; + } + } + InvNameObjMsg(scriptID,data->int_val,data->str_val,objp->name); + strcpy(data->str_val,objp->name); + UpdateAllParentNodesText(node); + AddObjectToList(data->str_val); + return 0; + } + + // All is cool, so just add the name + AddObjectToList(objp->name); + } + break; + case ROOM_PARAMETER_TYPE: + { + // Check for not specified rooms + if(data->int_val == NOT_SPECIFIED_TYPE) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Room"); + return 1; + } + + // Check for invalid rooms + int r=data->int_val; + if(r<0 || r>Highest_room_index || !Rooms[r].used || Rooms[r].name==NULL) { + int index=osipf_FindRoomName(data->str_val); + if(index>=0) { + if(InvIndValPrompt(scriptID,"Room",r,data->str_val,index)==IDYES) { + data->int_val=index; + UpdateAllParentNodesText(node); + AddRoomToList(data->str_val); + return 0; + } + } + InvIndValMsg(scriptID,"Room",r,data->str_val); + data->int_val=NOT_SPECIFIED_TYPE; + strcpy(data->str_val,""); + UpdateAllParentNodesText(node); + return 1; + } + + // Check for invalid room names + if(strcmp(data->str_val,Rooms[r].name)!=0) { + int index=osipf_FindRoomName(data->str_val); + if(index>=0) { + if(InvNameIndValPrompt(scriptID,"Room",r,data->str_val,Rooms[r].name,index)==IDYES) { + data->int_val=index; + UpdateAllParentNodesText(node); + AddRoomToList(data->str_val); + return 0; + } + } + InvNameIndValMsg(scriptID,"Room",r,data->str_val,Rooms[r].name); + strcpy(data->str_val,Rooms[r].name); + UpdateAllParentNodesText(node); + AddRoomToList(data->str_val); + return 0; + } + + // All is cool, so just add the name + AddRoomToList(Rooms[r].name); + } + break; + case TRIGGER_PARAMETER_TYPE: + { + // Check for not specified triggers + if(data->int_val == NOT_SPECIFIED_TYPE) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Trigger"); + return 1; + } + + // Check for invalid triggers + int t=data->int_val; + if(t<0 || t>=Num_triggers || t>=MAX_NAMED_TRIGGERS || strlen(Triggers[t].name)==0) { + int index=osipf_FindTriggerName(data->str_val); + if(index>=0) { + if(InvIndValPrompt(scriptID,"Trigger",t,data->str_val,index)==IDYES) { + data->int_val=index; + UpdateAllParentNodesText(node); + AddTriggerToList(data->str_val); + return 0; + } + } + InvIndValMsg(scriptID,"Trigger",t,data->str_val); + data->int_val=NOT_SPECIFIED_TYPE; + strcpy(data->str_val,""); + UpdateAllParentNodesText(node); + return 1; + } + + // Check for invalid trigger names + if(strcmp(data->str_val,Triggers[t].name)!=0) { + int index=osipf_FindTriggerName(data->str_val); + if(index>=0) { + if(InvNameIndValPrompt(scriptID,"Trigger",t,data->str_val,Triggers[t].name,index)==IDYES) { + data->int_val=index; + UpdateAllParentNodesText(node); + AddTriggerToList(data->str_val); + return 0; + } + } + InvNameIndValMsg(scriptID,"Trigger",t,data->str_val,Triggers[t].name); + strcpy(data->str_val,Triggers[t].name); + UpdateAllParentNodesText(node); + AddTriggerToList(data->str_val); + return 0; + } + + // All is cool, so just add the name + AddTriggerToList(Triggers[t].name); + } + break; + case SOUND_PARAMETER_TYPE: + { + // Check for not specified sounds + if(data->int_val == NOT_SPECIFIED_TYPE) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Sound"); + return 1; + } + + // Check for invalid sounds + int s=data->int_val; + if(s<0 || s>=MAX_SOUNDS || !Sounds[s].used) { + int index=osipf_FindSoundName(data->str_val); + if(index>=0) { + if(InvIndValPrompt(scriptID,"Sound",s,data->str_val,index)==IDYES) { + data->int_val=index; + UpdateAllParentNodesText(node); + AddSoundToList(data->str_val); + return 0; + } + } + InvIndValMsg(scriptID,"Sound",s,data->str_val); + data->int_val=NOT_SPECIFIED_TYPE; + strcpy(data->str_val,""); + UpdateAllParentNodesText(node); + return 1; + } + + // Check for invalid sound names + if(strcmp(data->str_val,Sounds[s].name)!=0) { + int index=osipf_FindSoundName(data->str_val); + if(index>=0) { + if(InvNameIndValPrompt(scriptID,"Sound",s,data->str_val,Sounds[s].name,index)==IDYES) { + data->int_val=index; + UpdateAllParentNodesText(node); + AddSoundToList(data->str_val); + return 0; + } + } + InvNameIndValMsg(scriptID,"Sound",s,data->str_val,Sounds[s].name); + strcpy(data->str_val,Sounds[s].name); + UpdateAllParentNodesText(node); + AddSoundToList(data->str_val); + return 0; + } + + // All is cool, so just add the name + AddSoundToList(Sounds[s].name); + } + break; + case TEXTURE_PARAMETER_TYPE: + { + // Check for not specified textures + if(data->int_val == NOT_SPECIFIED_TYPE) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Texture"); + return 1; + } + + // Check for invalid textures + int t=data->int_val; + if(t<0 || t>=MAX_TEXTURES || !GameTextures[t].used) { + int index=osipf_FindTextureName(data->str_val); + if(index>=0) { + if(InvIndValPrompt(scriptID,"Texture",t,data->str_val,index)==IDYES) { + data->int_val=index; + UpdateAllParentNodesText(node); + AddTextureToList(data->str_val); + return 0; + } + } + InvIndValMsg(scriptID,"Texture",t,data->str_val); + data->int_val=NOT_SPECIFIED_TYPE; + strcpy(data->str_val,""); + UpdateAllParentNodesText(node); + return 1; + } + + // Check for invalid texture names + if(strcmp(data->str_val,GameTextures[t].name)!=0) { + int index=osipf_FindTextureName(data->str_val); + if(index>=0) { + if(InvNameIndValPrompt(scriptID,"Texture",t,data->str_val,GameTextures[t].name,index)==IDYES) { + data->int_val=index; + UpdateAllParentNodesText(node); + AddTextureToList(data->str_val); + return 0; + } + } + InvNameIndValMsg(scriptID,"Texture",t,data->str_val,GameTextures[t].name); + strcpy(data->str_val,GameTextures[t].name); + UpdateAllParentNodesText(node); + AddTextureToList(data->str_val); + return 0; + } + + // All is cool, so just add the name + AddTextureToList(GameTextures[t].name); + } + break; + case PATH_PARAMETER_TYPE: + { + // Check for not specified paths + if(data->int_val == NOT_SPECIFIED_TYPE) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Path"); + return 1; + } + + // Check for invalid paths + int t=data->int_val; + if(t<0 || t>=MAX_GAME_PATHS || !GamePaths[t].used) { + int index=osipf_FindPathName(data->str_val); + if(index>=0) { + if(InvIndValPrompt(scriptID,"Path",t,data->str_val,index)==IDYES) { + data->int_val=index; + UpdateAllParentNodesText(node); + AddPathToList(data->str_val); + return 0; + } + } + InvIndValMsg(scriptID,"Path",t,data->str_val); + data->int_val=NOT_SPECIFIED_TYPE; + strcpy(data->str_val,""); + UpdateAllParentNodesText(node); + return 1; + } + + // Check for invalid path names + if(strcmp(data->str_val,GamePaths[t].name)!=0) { + int index=osipf_FindPathName(data->str_val); + if(index>=0) { + if(InvNameIndValPrompt(scriptID,"Path",t,data->str_val,GamePaths[t].name,index)==IDYES) { + data->int_val=index; + UpdateAllParentNodesText(node); + AddPathToList(data->str_val); + return 0; + } + } + InvNameIndValMsg(scriptID,"Path",t,data->str_val,GamePaths[t].name); + strcpy(data->str_val,GamePaths[t].name); + UpdateAllParentNodesText(node); + AddPathToList(data->str_val); + return 0; + } + + // All is cool, so just add the name + AddPathToList(GamePaths[t].name); + } + break; + case MATCEN_PARAMETER_TYPE: + { + // Check for MATCEN ID + if(data->subID==USE_MATCEN_EVENT_ID) { + if(ScriptHasAMatcenID(node)) { + return 0; + } + else { + InvSpecParamMsg(scriptID,"a MATCEN ID (Matcen type)"); + return 1; + } + } + + // Check for not specified matcens + if(data->int_val == NOT_SPECIFIED_TYPE) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Matcen"); + return 1; + } + + // Check for invalid matcens + int t=data->int_val; + if(!MatcenValid(t)) { + int index=osipf_FindMatcenName(data->str_val); + if(index>=0) { + if(InvIndValPrompt(scriptID,"Matcen",t,data->str_val,index)==IDYES) { + data->int_val=index; + UpdateAllParentNodesText(node); + AddMatcenToList(data->str_val); + return 0; + } + } + InvIndValMsg(scriptID,"Matcen",t,data->str_val); + data->int_val=NOT_SPECIFIED_TYPE; + strcpy(data->str_val,""); + UpdateAllParentNodesText(node); + return 1; + } + + // Check for invalid matcen names + char matcen_name[MAX_MATCEN_NAME_LEN+1]; + Matcen[t]->GetName(matcen_name); + if(strcmp(data->str_val,matcen_name)!=0) { + int index=osipf_FindMatcenName(data->str_val); + if(index>=0) { + if(InvNameIndValPrompt(scriptID,"Matcen",t,data->str_val,matcen_name,index)==IDYES) { + data->int_val=index; + UpdateAllParentNodesText(node); + AddMatcenToList(data->str_val); + return 0; + } + } + InvNameIndValMsg(scriptID,"Matcen",t,data->str_val,matcen_name); + strcpy(data->str_val,matcen_name); + UpdateAllParentNodesText(node); + AddMatcenToList(data->str_val); + return 0; + } + + // All is cool, so just add the name + AddMatcenToList(matcen_name); + } + break; + case LEVEL_GOAL_PARAMETER_TYPE: + { + // Check for LEVEL GOAL ID + if(data->subID==USE_LEVEL_GOAL_ID) { + if(ScriptHasALevelGoalID(node)) { + return 0; + } + else { + InvSpecParamMsg(scriptID,"a LEVEL GOAL ID (Level Goal type)"); + return 1; + } + } + + // Check for not specified level goals + if(data->int_val == NOT_SPECIFIED_TYPE) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Level Goal"); + return 1; + } + + // Check for invalid level goals + int t=osipf_FindLevelGoalName(data->str_val); + if(t<0) { + InvIndValMsg(scriptID,"Level Goal",t,data->str_val); + data->int_val=NOT_SPECIFIED_TYPE; + strcpy(data->str_val,""); + UpdateAllParentNodesText(node); + return 1; + } + data->int_val=t; + + // All is cool, so just add the name + AddGoalToList(data->str_val); + } + break; + case STRM_AUDIO_PARAMETER_TYPE: + { + // Check for not specified streaming audio filenames + if(strlen(data->str_val)==0) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Streaming Audio File"); + return 1; + } + + // Check if filename is invalid + if(!GamefileExists(data->str_val)) { + InvIndValMsg(scriptID,"Streaming Audio File",0,data->str_val); + strcpy(data->str_val,""); + UpdateAllParentNodesText(node); + return 1; + } + + // All is cool, so just add the name + AddStrmAudioToList(data->str_val); + } + break; + case SPECNAME_PARAMETER_TYPE: + { + // Check for not specified special names + if(strlen(data->str_val)==0) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Specific Name"); + return 1; + } + + // All is cool, so just add the name + AddSpecnameToList(data->str_val); + } + break; + case STRING_PARAMETER_TYPE: + { + // Check for not specified messages + if(strlen(data->str_val)==0) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Message ID"); + return 1; + } + + // Check if message name is invalid + if(FindMessageInList(data->str_val)==NULL) { + InvIndValMsg(scriptID,"Message ID",0,data->str_val); + strcpy(data->str_val,""); + UpdateAllParentNodesText(node); + return 1; + } + + // All is cool, so just add the message name + AddMessageNameToList(data->str_val); + } + break; + case ENUM_PARAMETER_TYPE: + { + // Check for GOAL ID and TIMER ID handles + if(data->subID==USE_GOALID_VALUE) { + if(ScriptHasAGoalID(node)) { + return 0; + } + else { + InvSpecParamMsg(scriptID,"a GOAL ID (Enumerated type:GoalID)"); + return 1; + } + } + + if(data->subID==USE_TIMERID_VALUE) { + if(ScriptHasATimerID(node)) { + return 0; + } + else { + InvSpecParamMsg(scriptID,"a TIMER ID (Enumerated type:TimerID)"); + return 1; + } + } + + if(data->subID==USE_MATCENID_VALUE) { + if(ScriptHasAMatcenID(node)) { + return 0; + } + else { + InvSpecParamMsg(scriptID,"a MATCEN ID (Enumerated type:MatcenID)"); + return 1; + } + } + + // Check for invalid enums + if(GetEnumValueName(data->name,data->int_val)==NULL) { + IndValNotSpecMsg(scriptID,"Enumerated Type"); + UpdateAllParentNodesText(node); + return 1; + } + } + break; + case SCRIPT_PARAMETER_TYPE: + { + // Check for NOT SPECIFIED script ID's + if(data->int_val==NOT_SPECIFIED_TYPE) { + if(show_notspec_warnings) + IndValNotSpecMsg(scriptID,"Script ID"); + return 1; + } + + // Check for invalid script ID's + if(FindScriptIDNode(data->int_val)==NULL) { + InvIndValMsg(scriptID,"Script ID",data->int_val,"Unknown"); + data->int_val=NOT_SPECIFIED_TYPE; + UpdateAllParentNodesText(node); + return 1; + } + } + break; + } + return 0; + } + + return 0; +} + + +// Displays the invalid special parameter warning message +void CDallasMainDlg::InvSpecParamMsg(int scriptID, char *type_name) +{ + CString msg, title; + + if(type_name==NULL) return; + + msg.Format("WARNING: Script #%d references %s even though its selected event (or owner) type does not support one.",scriptID,type_name); + title.Format("Invalid Special Parameter Warning!"); + MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); +} + + +// Displays the NOT SPECIFIED indexed value warning message +void CDallasMainDlg::IndValNotSpecMsg(int scriptID, char *type_name) +{ + CString msg, title; + + if(type_name==NULL) return; + + msg.Format("WARNING: Script #%d references a %s which has not been specified.",scriptID,type_name); + title.Format("%s Not Specified Warning!",type_name); + MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); +} + + +// Displays the invalid indexed value warning message +void CDallasMainDlg::InvIndValMsg(int scriptID, char *type_name, int index, char *name) +{ + CString msg, title; + + if(type_name==NULL || name==NULL) return; + + msg.Format("WARNING: Script #%d references a %s (index=%d, name=%s) that no longer exists. It will be changed to NOT SPECIFIED.",scriptID,type_name,index,name); + title.Format("Invalid %s Warning!",type_name); + MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); +} + + +// Displays the invalid indexed value prompt +int CDallasMainDlg::InvIndValPrompt(int scriptID, char *type_name, int index, char *name, int new_index) +{ + CString msg, title; + + if(type_name==NULL || name==NULL) return(IDNO); + + msg.Format("WARNING: Script #%d references a %s (index=%d, name=%s) that no longer exists. However, another %s (index=%d) exists with the same name.\n\nDo you want to use this other one instead?",scriptID,type_name,index,name,type_name,new_index); + title.Format("Invalid %s Warning!",type_name); + return(MessageBox(msg,title,MB_YESNO|MB_ICONEXCLAMATION)); +} + + +// Displays the invalid indexed value name warning message +void CDallasMainDlg::InvNameIndValMsg(int scriptID, char *type_name, int index, char *name, char *new_name) +{ + CString msg, title; + + if(type_name==NULL || name==NULL || new_name==NULL) return; + + msg.Format("WARNING: Script #%d references a %s (index=%d, name=%s) whose name has changed to \"%s\". Its name will be updated.",scriptID,type_name,index,name,new_name); + title.Format("Invalid %s Name Warning!",type_name); + MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); +} + + +// Displays the invalid indexed value name prompt +int CDallasMainDlg::InvNameIndValPrompt(int scriptID, char *type_name, int index, char *name, char *new_name, int new_index) +{ + CString msg, title; + + if(type_name==NULL || name==NULL || new_name==NULL) return(IDNO); + + msg.Format("WARNING: Script #%d references a %s (index=%d, name=%s) whose name has changed to \"%s\". However, another %s (index=%d) exists with the old name.\n\nDo you want to use this other one instead?",scriptID,type_name,index,name,new_name,type_name,new_index); + title.Format("Invalid %s Name Warning!",type_name); + return(MessageBox(msg,title,MB_YESNO|MB_ICONEXCLAMATION)); +} + + +// Displays the invalid Object warning message +void CDallasMainDlg::InvObjMsg(int scriptID, int handle, char *name) +{ + CString msg, title; + + if(name==NULL) return; + + msg.Format("WARNING: Script #%d references an Object (handle=%d, name=%s) that no longer exists. It will be changed to Object NONE.",scriptID,handle,name); + title.Format("Invalid Object Warning!"); + MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); +} + + +// Displays the invalid Object prompt +int CDallasMainDlg::InvObjPrompt(int scriptID, int handle, char *name, int new_handle) +{ + CString msg, title; + + if(name==NULL) return(IDNO); + + msg.Format("WARNING: Script #%d references an Object (handle=%d, name=%s) that no longer exists. However, another object (handle=%d) exists with the same name.\n\nDo you want to use this other one instead?",scriptID,handle,name,new_handle); + title.Format("Invalid Object Warning!"); + return(MessageBox(msg,title,MB_YESNO|MB_ICONEXCLAMATION)); +} + + +// Displays the invalid object name warning message +void CDallasMainDlg::InvNameObjMsg(int scriptID, int handle, char *name, char *new_name) +{ + CString msg, title; + + if(name==NULL || new_name==NULL) return; + + msg.Format("WARNING: Script #%d references an Object (handle=%d, name=%s) whose name has changed to \"%s\". Its name will be updated.",scriptID,handle,name,new_name); + title.Format("Invalid Object Name Warning!"); + MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); +} + + +// Displays the invalid object name prompt +int CDallasMainDlg::InvNameObjPrompt(int scriptID, int handle, char *name, char *new_name, int new_handle) +{ + CString msg, title; + + if(name==NULL || new_name==NULL) return(IDNO); + + msg.Format("WARNING: Script #%d references an Object (handle=%d, name=%s) whose name has changed to \"%s\". However, another object (handle=%d) exists with the old name.\n\nDo you want to use this other one instead?",scriptID,handle,name,new_name,new_handle); + title.Format("Invalid Object Name Warning!"); + return(MessageBox(msg,title,MB_YESNO|MB_ICONEXCLAMATION)); +} + + + + +// Adds the given door name to the door name list +int CDallasMainDlg::AddDoorToList(char *name) +{ + // Make sure we've got a name + if(name==NULL || strlen(name)==0) return FALSE; + + // See if it's already in the list + if(FindDoorInList(name)>=0) return TRUE; + + // If there's room in the list, add the new name + if(m_DoorListSize>=MAX_NAMED_DOORS) return FALSE; + + int pos=m_DoorListSize; + m_DoorList[pos]=(char *)mem_malloc(strlen(name)+1); + if(m_DoorList[pos]==NULL) { + MessageBox("Out of memory in AddDoorToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + strcpy(m_DoorList[pos],name); + m_DoorListSize++; + + return TRUE; +} + +// Returns the list index of the given door name (or -1 if not found) +int CDallasMainDlg::FindDoorInList(char *name) +{ + if(name==NULL) return(-1); + + for(int j=0;j=0) return TRUE; + + // If there's room in the list, add the new name + if(m_ObjectListSize>=MAX_NAMED_OBJECTS) return FALSE; + + int pos=m_ObjectListSize; + m_ObjectList[pos]=(char *)mem_malloc(strlen(name)+1); + if(m_ObjectList[pos]==NULL) { + MessageBox("Out of memory in AddObjectToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + strcpy(m_ObjectList[pos],name); + m_ObjectListSize++; + + return TRUE; +} + +// Returns the list index of the given object name (or -1 if not found) +int CDallasMainDlg::FindObjectInList(char *name) +{ + if(name==NULL) return(-1); + + for(int j=0;j=0) return TRUE; + + // If there's room in the list, add the new name + if(m_RoomListSize>=MAX_NAMED_ROOMS) return FALSE; + + int pos=m_RoomListSize; + m_RoomList[pos]=(char *)mem_malloc(strlen(name)+1); + if(m_RoomList[pos]==NULL) { + MessageBox("Out of memory in AddRoomToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + strcpy(m_RoomList[pos],name); + m_RoomListSize++; + + return TRUE; +} + +// Returns the list index of the given room name (or -1 if not found) +int CDallasMainDlg::FindRoomInList(char *name) +{ + if(name==NULL) return(-1); + + for(int j=0;j=0) return TRUE; + + // If there's Trigger in the list, add the new name + if(m_TriggerListSize>=MAX_NAMED_TRIGGERS) return FALSE; + + int pos=m_TriggerListSize; + m_TriggerList[pos]=(char *)mem_malloc(strlen(name)+1); + if(m_TriggerList[pos]==NULL) { + MessageBox("Out of memory in AddTriggerToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + strcpy(m_TriggerList[pos],name); + m_TriggerListSize++; + + return TRUE; +} + +// Returns the list index of the given Trigger name (or -1 if not found) +int CDallasMainDlg::FindTriggerInList(char *name) +{ + if(name==NULL) return(-1); + + for(int j=0;j=0) return TRUE; + + // If there's room in the list, add the new name + if(m_SoundListSize>=MAX_NAMED_SOUNDS) return FALSE; + + int pos=m_SoundListSize; + m_SoundList[pos]=(char *)mem_malloc(strlen(name)+1); + if(m_SoundList[pos]==NULL) { + MessageBox("Out of memory in AddSoundToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + strcpy(m_SoundList[pos],name); + m_SoundListSize++; + + return TRUE; +} + +// Returns the list index of the given sound name (or -1 if not found) +int CDallasMainDlg::FindSoundInList(char *name) +{ + if(name==NULL) return(-1); + + for(int j=0;j=0) return TRUE; + + // If there's room in the list, add the new name + if(m_TextureListSize>=MAX_NAMED_TEXTURES) return FALSE; + + int pos=m_TextureListSize; + m_TextureList[pos]=(char *)mem_malloc(strlen(name)+1); + if(m_TextureList[pos]==NULL) { + MessageBox("Out of memory in AddTextureToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + strcpy(m_TextureList[pos],name); + m_TextureListSize++; + + return TRUE; +} + +// Returns the list index of the given Texture name (or -1 if not found) +int CDallasMainDlg::FindTextureInList(char *name) +{ + if(name==NULL) return(-1); + + for(int j=0;j=0) return TRUE; + + // If there's room in the list, add the new name + if(m_SpecnameListSize>=MAX_SPECNAMES) return FALSE; + + int pos=m_SpecnameListSize; + m_SpecnameList[pos]=(char *)mem_malloc(strlen(name)+1); + if(m_SpecnameList[pos]==NULL) { + MessageBox("Out of memory in AddSpecnameToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + strcpy(m_SpecnameList[pos],name); + m_SpecnameListSize++; + + return TRUE; +} + +// Returns the list index of the given Specname name (or -1 if not found) +int CDallasMainDlg::FindSpecnameInList(char *name) +{ + if(name==NULL) return(-1); + + for(int j=0;j=0) return TRUE; + + // If there's room in the list, add the new name + if(m_PathListSize>=MAX_NAMED_PATHS) return FALSE; + + int pos=m_PathListSize; + m_PathList[pos]=(char *)mem_malloc(strlen(name)+1); + if(m_PathList[pos]==NULL) { + MessageBox("Out of memory in AddPathToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + strcpy(m_PathList[pos],name); + m_PathListSize++; + + return TRUE; +} + +// Returns the list index of the given Path name (or -1 if not found) +int CDallasMainDlg::FindPathInList(char *name) +{ + if(name==NULL) return(-1); + + for(int j=0;j=0) return TRUE; + + // If there's room in the list, add the new name + if(m_MatcenListSize>=MAX_NAMED_MATCENS) return FALSE; + + int pos=m_MatcenListSize; + m_MatcenList[pos]=(char *)mem_malloc(strlen(name)+1); + if(m_MatcenList[pos]==NULL) { + MessageBox("Out of memory in AddMatcenToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + strcpy(m_MatcenList[pos],name); + m_MatcenListSize++; + + return TRUE; +} + +// Returns the list index of the given Matcen name (or -1 if not found) +int CDallasMainDlg::FindMatcenInList(char *name) +{ + if(name==NULL) return(-1); + + for(int j=0;j=0) return TRUE; + + // If there's room in the list, add the new name + if(m_GoalListSize>=MAX_NAMED_GOALS) return FALSE; + + int pos=m_GoalListSize; + m_GoalList[pos]=(char *)mem_malloc(strlen(name)+1); + if(m_GoalList[pos]==NULL) { + MessageBox("Out of memory in AddGoalToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + strcpy(m_GoalList[pos],name); + m_GoalListSize++; + + return TRUE; +} + +// Returns the list index of the given Goal name (or -1 if not found) +int CDallasMainDlg::FindGoalInList(char *name) +{ + if(name==NULL) return(-1); + + for(int j=0;j=0) return TRUE; + + // If there's room in the list, add the new name + if(m_StrmAudioListSize>=MAX_NAMED_STRM_AUDIO) return FALSE; + + int pos=m_StrmAudioListSize; + m_StrmAudioList[pos]=(char *)mem_malloc(strlen(name)+1); + if(m_StrmAudioList[pos]==NULL) { + MessageBox("Out of memory in AddStrmAudioToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + strcpy(m_StrmAudioList[pos],name); + m_StrmAudioListSize++; + + return TRUE; +} + +// Returns the list index of the given StrmAudio name (or -1 if not found) +int CDallasMainDlg::FindStrmAudioInList(char *name) +{ + if(name==NULL) return(-1); + + for(int j=0;j=0) return TRUE; + + // If there's room in the list, add the new name + if(m_MessageNameListSize>=MAX_MESSAGE_LIST_ENTRIES) return FALSE; + + int pos=m_MessageNameListSize; + m_MessageNameList[pos]=(char *)mem_malloc(strlen(name)+1); + if(m_MessageNameList[pos]==NULL) { + MessageBox("Out of memory in AddMessageNameToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + strcpy(m_MessageNameList[pos],name); + m_MessageNameListSize++; + + return TRUE; +} + +// Returns the list index of the given MessageName name (or -1 if not found) +int CDallasMainDlg::FindMessageNameInList(char *name) +{ + if(name==NULL) return(-1); + + for(int j=0;jResetContent(); + + // Add the User Type Names + for(j=0;jAddString(m_EnumDatabase[j].name); + types_added++; + } + } + + // Select the first one + box->SetCurSel(0); + + return(types_added); +} + + +// Fills the box with all values for the given User Type +int CDallasMainDlg::FillValuesBox(CListBox *box, char *utype_name) +{ + int j, DBslot, values_added; + + values_added=0; + + // Clear the box + box->ResetContent(); + + // Fill in the values + DBslot=GetEnumID(utype_name); + if(DBslot==INVALID_ENUM) return(values_added); + + for(j=0;jvalue!=-1) { + box->AddString(value_entry->name); + values_added++; + } + } + + // Select the first one + box->SetCurSel(0); + + return(values_added); +} + + +// Adds a value to the user type +// Returns the new position in list, or -1 if add failed +int CDallasMainDlg::AddUserTypeValue(char *utype_name, char *value_name) +{ + int j, k, DBslot, new_value; + + if(utype_name==NULL || value_name==NULL) return(-1); + + new_value=-1; + + DBslot=GetEnumID(utype_name); + if(DBslot==INVALID_ENUM) return(-1); + + tEnumDBEntry *entry=&m_EnumDatabase[DBslot]; + if(entry->num_values>=(entry->max_values+2) || entry->num_values>=MAX_ENUM_VALUES) return(-1); + + // Find a place to insert the new value + new_value=0; + for(j=0;jnum_values;j++) { + tEnumValueEntry *value_entry=&entry->values[j]; + if(new_value < value_entry->value) { + // Bump the higher ones down the list + for(k=entry->num_values;k>j;k--) { + entry->values[k].value=entry->values[k-1].value; + entry->values[k].name=entry->values[k-1].name; + } + break; + } + new_value=value_entry->value+1; + } + + // Store the new value at the current position + tEnumValueEntry *value_entry=&entry->values[j]; + value_entry->value=new_value; + value_entry->name=(char *)mem_malloc(strlen(value_name)+1); + if(value_entry->name==NULL) { + MessageBox("ERROR: Out of mem in AddUserTypeValue()!","Error!"); + return(-1); + } + strcpy(value_entry->name,value_name); + + entry->num_values++; + + SetModified(TRUE); + + return(j); +} + + +// Removes a value +int CDallasMainDlg::DeleteUserTypeValue(char *utype_name, char *value_name) +{ + int j, k, DBslot; + + if(utype_name==NULL || value_name==NULL) return FALSE; + + DBslot=GetEnumID(utype_name); + if(DBslot==INVALID_ENUM) return FALSE; + + tEnumDBEntry *entry=&m_EnumDatabase[DBslot]; + + // Find the value name in the list + for(j=0;jnum_values;j++) { + tEnumValueEntry *value_entry=&entry->values[j]; + if(strcmp(value_name,value_entry->name)==0) { + // Free the name memory + mem_free(value_entry->name); + + // Compact the list + entry->num_values--; + for(k=j;k<(entry->num_values);k++) { + entry->values[k].value=entry->values[k+1].value; + entry->values[k].name=entry->values[k+1].name; + } + entry->values[k].name=NULL; + SetModified(TRUE); + return TRUE; + } + } + + return FALSE; +} + + +// Changes the name of a value +int CDallasMainDlg::ChangeValueName(char *utype_name, char *old_name, char *new_name) +{ + int j, DBslot; + + if(utype_name==NULL || old_name==NULL || new_name==NULL) return FALSE; + + DBslot=GetEnumID(utype_name); + if(DBslot==INVALID_ENUM) return FALSE; + + tEnumDBEntry *entry=&m_EnumDatabase[DBslot]; + + // Find the value name in the list + for(j=0;jnum_values;j++) { + tEnumValueEntry *value_entry=&entry->values[j]; + if(strcmp(old_name,value_entry->name)==0) { + // Free the name memory + mem_free(value_entry->name); + + // Add the new name + value_entry->name=(char *)mem_malloc(strlen(new_name)+1); + if(value_entry->name==NULL) { + MessageBox("ERROR: Out of mem in ChangeValueName()!","Error!"); + return FALSE; + } + strcpy(value_entry->name,new_name); + SetModified(TRUE); + + return TRUE; + } + } + + return FALSE; +} + + +///////////////////////////////////////////////////////////////////////////// +// Enumeration Database Functions +///////////////////////////////////////////////////////////////////////////// + +// Initializes the enum DB for use +void CDallasMainDlg::InitEnumDatabase(void) +{ + int j,k; + + for(j=0;jAppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+i, name.GetBuffer(0)); + enum_types_added++; + } + else + enum_menu->AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, command_offset+i, name.GetBuffer(0)); + } + + return(enum_types_added); +} + + +// Fills up the given menu with the enumeration values of the given enum name +// NOTE: Command ID's of objects items start at the given command_offset +int CDallasMainDlg::FillEnumValuesMenu(CMenu *enum_menu, int command_offset, char *enum_name) +{ + int enum_values_added; + int i, DBslot; + tEnumDBEntry *enum_entry; + + // Set the counts + enum_values_added=0; + + // Find the correct enum database entry + DBslot=GetEnumID(enum_name); + if(DBslot==INVALID_ENUM) return 0; + + enum_entry=&m_EnumDatabase[DBslot]; + + // Fill the menu with names of matching enumeration values + for (i=0;inum_values;i++) { + enum_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+i, enum_entry->values[i].name); + enum_values_added++; + } + + return(enum_values_added); +} + + +///////////////////////////////////////////////////////////////////////////// +// Flag Database Functions +///////////////////////////////////////////////////////////////////////////// + +// Initializes the Flag DB for use +void CDallasMainDlg::InitFlagDatabase(void) +{ + int j,k; + + for(j=0;jAppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+i, m_FlagDatabase[i].name); + flag_types_added++; + } + else + flag_menu->AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, command_offset+i, m_FlagDatabase[i].name); + } + + return(flag_types_added); +} + + +// Fills up the given CCheckListBox with the flag values of the given flag name +int CDallasMainDlg::FillFlagValuesBox(CCheckListBox *box, char *flag_name, int flags_value, int valid_flags_mask) +{ + int flag_values_added; + int i, DBslot; + tFlagDBEntry *flag_entry; + + // Set the counts + flag_values_added=0; + + // Find the correct enum database entry + DBslot=GetFlagID(flag_name); + if(DBslot==INVALID_FLAG) return 0; + + flag_entry=&m_FlagDatabase[DBslot]; + + // Fill the box with names of matching flag values + for (i=0;inum_values;i++) { + if(valid_flags_mask==0 || (flag_entry->values[i].value & valid_flags_mask)) { + int index; + index=box->AddString(flag_entry->values[i].name); + if(index!=LB_ERR) { + box->SetItemData(index,flag_entry->values[i].value); + if(flag_entry->values[i].value & flags_value) + box->SetCheck(index,1); + else + box->SetCheck(index,0); + + /* In case you just wanna dim the invalid flags + if(valid_flags_mask==0 || (flag_entry->values[i].value & valid_flags_mask)) + box->Enable(index,TRUE); + else + box->Enable(index,FALSE); + */ + } + flag_values_added++; + } + } + + return(flag_values_added); +} + + +///////////////////////////////////////////////////////////////////////////// +// Action and Query Database Functions +///////////////////////////////////////////////////////////////////////////// + +// Initialize the Database Arrays +void CDallasMainDlg::InitFunctionDatabases(void) +{ + int j; + + for(j=0;j=m_NumActions) return NULL; + + return(m_ActionDatabase[ID].desc); +} + +// Returns a pointer to the action help text +char *CDallasMainDlg::GetActionHelp(int ID) +{ + if(ID<0 || ID>=m_NumActions) return NULL; + + return(m_ActionDatabase[ID].help); +} + +// Returns a pointer to the action function name +char *CDallasMainDlg::GetActionFunc(int ID) +{ + if(ID==DO_NOTHING_ID) return DO_NOTHING_STRING; + + if(ID<0 || ID>=m_NumActions) return INVALID_FUNCTION_NAME; + + return(m_ActionDatabase[ID].func); +} + +// Searches action list for action matching given function name +int CDallasMainDlg::GetActionFuncID(char *func_name) +{ + if(func_name==NULL) return INVALID_FUNCTION_ID; + + if(strcmp(DO_NOTHING_STRING, func_name)==0) return DO_NOTHING_ID; + + for(int j=0;j=m_NumQueries) return NULL; + + return(m_QueryDatabase[ID].desc); +} + +// Returns a pointer to the query help text +char *CDallasMainDlg::GetQueryHelp(int ID) +{ + if(ID<0 || ID>=m_NumQueries) return NULL; + + return(m_QueryDatabase[ID].help); +} + +// Returns a pointer to the query function name +char *CDallasMainDlg::GetQueryFunc(int ID) +{ + if(ID<0 || ID>=m_NumQueries) return INVALID_FUNCTION_NAME; + + return(m_QueryDatabase[ID].func); +} + +// Searches query list for query matching given function name +int CDallasMainDlg::GetQueryFuncID(char *func_name) +{ + if(func_name==NULL) return INVALID_FUNCTION_ID; + + for(int j=0;jname = (char *) mem_malloc(strlen(enum_name)+1); + if(enum_entry->name == NULL) { + FunctionFileParseError(NO_MEM_ERR,linenum,filename); + cfclose(ifile); + return; + } + strcpy(enum_entry->name,enum_name); + enum_entry->num_values=0; + enum_entry->is_user_type=TRUE; + enum_entry->max_values=atoi(max_value_text); + if(enum_entry->max_values<0) enum_entry->max_values=0; + if(enum_entry->max_values>(MAX_ENUMS-2)) enum_entry->max_values=(MAX_ENUMS-2); + + // Add the default (-1:None) value + tEnumValueEntry *value_entry; + value_entry = &enum_entry->values[enum_entry->num_values++]; + value_entry->name = (char *) mem_malloc(strlen(USERTYPE_NONE)+1); + if(value_entry->name == NULL) { + FunctionFileParseError(NO_MEM_ERR,linenum,filename); + cfclose(ifile); + return; + } + strcpy(value_entry->name,USERTYPE_NONE); + value_entry->value=-1; + } + } + else if (strncmp(line,TAG_ENUM,strlen(TAG_ENUM))==0) { // Parse an enumeration block + tEnumDBEntry *enum_entry; + char *enum_name; + bool done; + + // Strip off the name of this enumeration type + enum_name=strtok(line,WHITESPACE_CHARS); + if(enum_name!=NULL) enum_name=strtok(NULL,""); + if(enum_name==NULL || GetEnumID(enum_name)!=INVALID_ENUM) { + FunctionFileParseError(INV_ENUM_ERR,linenum,filename); + enum_entry = NULL; + } + else if(m_NumEnums==MAX_ENUMS) { + FunctionFileParseError(MAX_ENUM_ERR,linenum,filename); + enum_entry = NULL; + } + else { + enum_entry = &m_EnumDatabase[m_NumEnums++]; + enum_entry->name = (char *) mem_malloc(strlen(enum_name)+1); + if(enum_entry->name == NULL) { + FunctionFileParseError(NO_MEM_ERR,linenum,filename); + cfclose(ifile); + return; + } + strcpy(enum_entry->name,enum_name); + enum_entry->num_values=0; + enum_entry->is_user_type=FALSE; + enum_entry->max_values=0; + } + + // Parse the enumeration values for this entry + done = 0; + do { + + cf_ReadString(linebuf,sizeof(linebuf),ifile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,TAG_END,strlen(TAG_END)) == 0) + done = 1; + else if(enum_entry!=NULL) { + tEnumValueEntry *value_entry; + int enum_value; + char *enum_value_string; + char *enum_value_name; + + // Parse out the enum value and value name + enum_value_string=strtok(line,":"); + if(enum_value_string!=NULL) { + enum_value=atoi(enum_value_string); + enum_value_name=strtok(NULL,""); + } + + if(enum_value_string==NULL || enum_value_name==NULL || GetEnumValueName(enum_entry->name,enum_value)!=NULL) { + FunctionFileParseError(INV_ENUM_VALUE_ERR,linenum,filename); + value_entry = NULL; + } + else if(enum_entry->num_values==MAX_ENUM_VALUES) { + FunctionFileParseError(MAX_ENUM_VALUES_ERR,linenum,filename); + value_entry = NULL; + } + else { + value_entry = &enum_entry->values[enum_entry->num_values++]; + value_entry->name = (char *) mem_malloc(strlen(enum_value_name)+1); + if(value_entry->name == NULL) { + FunctionFileParseError(NO_MEM_ERR,linenum,filename); + cfclose(ifile); + return; + } + strcpy(value_entry->name,enum_value_name); + value_entry->value=enum_value; + } + } + + } while (!done && !cfeof(ifile)); + + if (!done) + FunctionFileParseError(UEOF_ERR,linenum,filename); + } + else if (strncmp(line,TAG_FLAG,strlen(TAG_FLAG))==0) { // Parse a flag block + tFlagDBEntry *flag_entry; + char *flag_name; + bool done; + + // Strip off the name of this flag type + flag_name=strtok(line,WHITESPACE_CHARS); + if(flag_name!=NULL) flag_name=strtok(NULL,""); + if(flag_name==NULL || GetFlagID(flag_name)!=INVALID_FLAG) { + FunctionFileParseError(INV_FLAG_ERR,linenum,filename); + flag_entry = NULL; + } + else if(m_NumFlags==MAX_FLAGS) { + FunctionFileParseError(MAX_FLAG_ERR,linenum,filename); + flag_entry = NULL; + } + else { + flag_entry = &m_FlagDatabase[m_NumFlags++]; + flag_entry->name = (char *) mem_malloc(strlen(flag_name)+1); + if(flag_entry->name == NULL) { + FunctionFileParseError(NO_MEM_ERR,linenum,filename); + cfclose(ifile); + return; + } + strcpy(flag_entry->name,flag_name); + flag_entry->num_values=0; + } + + // Parse the flag values for this entry + done = 0; + do { + + cf_ReadString(linebuf,sizeof(linebuf),ifile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,TAG_END,strlen(TAG_END)) == 0) + done = 1; + else if(flag_entry!=NULL) { + tFlagValueEntry *value_entry; + int flag_value; + char *flag_value_string; + char *flag_value_name; + + // Parse out the flag value and value name + flag_value_string=strtok(line,":"); + if(flag_value_string!=NULL) { + flag_value=atoi(flag_value_string); + flag_value_name=strtok(NULL,""); + } + + if(flag_value_string==NULL || flag_value_name==NULL || GetFlagValueName(flag_entry->name,flag_value)!=NULL) { + FunctionFileParseError(INV_FLAG_VALUE_ERR,linenum,filename); + value_entry = NULL; + } + else if(flag_entry->num_values==MAX_FLAG_VALUES) { + FunctionFileParseError(MAX_FLAG_VALUES_ERR,linenum,filename); + value_entry = NULL; + } + else { + value_entry = &flag_entry->values[flag_entry->num_values++]; + value_entry->name = (char *) mem_malloc(strlen(flag_value_name)+1); + if(value_entry->name == NULL) { + FunctionFileParseError(NO_MEM_ERR,linenum,filename); + cfclose(ifile); + return; + } + strcpy(value_entry->name,flag_value_name); + value_entry->value=flag_value; + } + } + + } while (!done && !cfeof(ifile)); + + if (!done) + FunctionFileParseError(UEOF_ERR,linenum,filename); + } + else if (strncmp(line,TAG_ACTION,strlen(TAG_ACTION)) == 0) { // Parse action block + if(m_NumActions>=MAX_ACTIONS) { + MessageBox("ERROR: The Maximum Action limit has been exceeded!\n\nParsing must stop immediately.","ERROR!"); + cfclose(ifile); + return; + } + tActionDBEntry *action = &m_ActionDatabase[m_NumActions++]; + if(m_NumActions==MAX_ACTIONS) { + MessageBox("Warning: The Maximum Action limit has been reached!","Warning!"); + } + + //Read category + cf_ReadString(linebuf,sizeof(linebuf),ifile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + action->category = GetFunctionCategoryID(line); + if(action->category==INVALID_CATEGORY) { + FunctionFileParseError(INV_CAT_ERR,linenum,filename); + cfclose(ifile); + return; + } + + //Read action description + cf_ReadString(linebuf,sizeof(linebuf),ifile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + action->desc = (char *) mem_malloc(strlen(line)+1); + if(action->desc==NULL) { + FunctionFileParseError(NO_MEM_ERR,linenum,filename); + cfclose(ifile); + return; + } + strcpy(action->desc,line); + + //Read action function + cf_ReadString(linebuf,sizeof(linebuf),ifile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + action->func = (char *) mem_malloc(strlen(line)+1); + if(action->func==NULL) { + FunctionFileParseError(NO_MEM_ERR,linenum,filename); + cfclose(ifile); + return; + } + strcpy(action->func,line); + + //Read help + bool done = 0; + helpbuf[0] = 0; + do { + + cf_ReadString(linebuf,sizeof(linebuf),ifile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,TAG_END,strlen(TAG_END)) == 0) + done = 1; + else { + strcat(helpbuf,line); + strcat(helpbuf,"\r\n"); + } + + } while (!done && !cfeof(ifile)); + + if (!done) + FunctionFileParseError(UEOF_ERR,linenum,filename); + + action->help = (char *) mem_malloc(strlen(helpbuf)+1); + if(action->help==NULL) { + FunctionFileParseError(NO_MEM_ERR,linenum,filename); + cfclose(ifile); + return; + } + strcpy(action->help,helpbuf); + } + else if (strncmp(line,TAG_QUERY,strlen(TAG_QUERY)) == 0) { // Parse Query block + if(m_NumQueries>=MAX_QUERIES) { + MessageBox("ERROR: The Maximum Query limit has been exceeded!\n\nParsing must stop immediately.","ERROR!"); + cfclose(ifile); + return; + } + tQueryDBEntry *query = &m_QueryDatabase[m_NumQueries++]; + if(m_NumQueries==MAX_QUERIES) { + MessageBox("Warning: The Maximum Query limit has been reached!","Warning!"); + } + + //Read category + cf_ReadString(linebuf,sizeof(linebuf),ifile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + query->category = GetFunctionCategoryID(line); + if(query->category==INVALID_CATEGORY) { + FunctionFileParseError(INV_CAT_ERR,linenum,filename); + cfclose(ifile); + return; + } + + //Read action description + cf_ReadString(linebuf,sizeof(linebuf),ifile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + query->desc = (char *) mem_malloc(strlen(line)+1); + if(query->desc==NULL) { + FunctionFileParseError(NO_MEM_ERR,linenum,filename); + cfclose(ifile); + return; + } + strcpy(query->desc,line); + + //Read action function + cf_ReadString(linebuf,sizeof(linebuf),ifile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + query->func = (char *) mem_malloc(strlen(line)+1); + if(query->func==NULL) { + FunctionFileParseError(NO_MEM_ERR,linenum,filename); + cfclose(ifile); + return; + } + strcpy(query->func,line); + + //Read help + bool done = 0; + helpbuf[0] = 0; + do { + + cf_ReadString(linebuf,sizeof(linebuf),ifile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,TAG_END,strlen(TAG_END)) == 0) + done = 1; + else { + strcat(helpbuf,line); + strcat(helpbuf,"\r\n"); + } + + } while (!done && !cfeof(ifile)); + + if (!done) + FunctionFileParseError(UEOF_ERR,linenum,filename); + + query->help = (char *) mem_malloc(strlen(helpbuf)+1); + if(query->help==NULL) { + FunctionFileParseError(NO_MEM_ERR,linenum,filename); + cfclose(ifile); + return; + } + strcpy(query->help,helpbuf); + } + } + + cfclose(ifile); +} + + +// Returns a description copy with the parameter type info removed +void CDallasMainDlg::ParseOutActionVarTypes(char *new_desc, char *old_desc) +{ + CString name_text, default_text, range_text; + CString new_desc_text; + + new_desc_text=""; + while((*old_desc)!='\0') { + + // If it's start of a param block, extract the param name + if((*old_desc)=='[') { + ParseParamBlock(old_desc,name_text,default_text,range_text); + new_desc_text+='['; + new_desc_text+=name_text; + new_desc_text+=']'; + } + else { + new_desc_text+=(*old_desc); + old_desc++; + } + } + + strcpy(new_desc,new_desc_text.GetBuffer(0)); +} + +/* OLD VERSION +// Returns a description copy with the parameter type info removed +void CDallasMainDlg::ParseOutActionVarTypes(char *new_desc, char *old_desc) +{ + int ok_to_write=TRUE; + + do { + if(ok_to_write) { + (*new_desc)=(*old_desc); + new_desc++; + } + + if((*old_desc)=='[') + ok_to_write=FALSE; + else if((*old_desc)==':') + ok_to_write=TRUE; + + old_desc++; + + } while((*old_desc)!='\0'); + + (*new_desc)=(*old_desc); +} +*/ + +// Returns a description copy with the parameter type info removed +void CDallasMainDlg::ParseOutQueryVarTypes(char *new_desc, char *old_desc) +{ + CString name_text, default_text, range_text; + CString new_desc_text; + + new_desc_text=""; + + // Skip the return type section + old_desc=strchr(old_desc,':'); + if(old_desc==NULL) { + strcpy(new_desc,new_desc_text.GetBuffer(0)); + return; + } + old_desc++; + + // Parse the rest like it was an action + ParseOutActionVarTypes(new_desc,old_desc); +} + +/* OLD VERSION +// Returns a description copy with the parameter type info removed +void CDallasMainDlg::ParseOutQueryVarTypes(char *new_desc, char *old_desc) +{ + int ok_to_write=FALSE; + + do { + if(ok_to_write) { + (*new_desc)=(*old_desc); + new_desc++; + } + + if((*old_desc)=='[') + ok_to_write=FALSE; + else if((*old_desc)==':') + ok_to_write=TRUE; + + old_desc++; + + } while((*old_desc)!='\0'); + + (*new_desc)=(*old_desc); +} +*/ + +// Validates an action node by conforming its parameters to what they should be +// returns FALSE if node was modified significantly, otherwise TRUE +bool CDallasMainDlg::ValidateActionNode(HTREEITEM node, int linenum) +{ + CString name_text, default_text, range_text; + tTreeNodeData *data; + HTREEITEM child_node; + int ID; + char *desc; + + if(node==NULL) return TRUE; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); + if(data==NULL || data->type!=ACTION_STATEMENT_NODE) return TRUE; + + ID=data->ID; + if(ID<0 || ID>=m_NumActions) return TRUE; + + desc=GetActionDesc(ID); + if(desc==NULL) return TRUE; + + // Get the first child, if one exists + child_node=m_ScriptTree.GetChildItem(node); + + // Parse the description, adding default parameter nodes appropriately + bool modified=FALSE; + while((*desc)!='\0') { + + if((*desc)=='[') { // Note the start of a parameter block + + int param_type=ParseParamBlock(desc,name_text,default_text,range_text); + if(param_type>=0) { + + // Check the corresponding param (if it exists) and make it match up + if(ConformParamNode(node,child_node,param_type,name_text.GetBuffer(0),default_text.GetBuffer(0))) + modified=TRUE; + + if(child_node!=NULL) child_node=m_ScriptTree.GetNextSiblingItem(child_node); + } + + } + else { + desc++; + } + } + + // Delete any remaining child parameter nodes (they are no longer used) + if(child_node!=NULL) { + do { + HTREEITEM temp_node=child_node; + child_node=m_ScriptTree.GetNextSiblingItem(child_node); + FreeTreeItem(temp_node); + } while(child_node!=NULL); + + modified=TRUE; + } + + if(modified) + ScriptFileParseError(MODIFIED_FUNC_ERR,linenum,GetScriptID(node),GetActionFunc(ID)); + + return (!modified); +} + +/* OLD VERSION +// Validates an action node by conforming its parameters to what they should be +// returns FALSE if node was modified significantly, otherwise TRUE +bool CDallasMainDlg::ValidateActionNode(HTREEITEM node, int linenum) +{ + tTreeNodeData *data; + HTREEITEM child_node; + int ID; + char *desc, *desc_copy; + + if(node==NULL) return TRUE; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); + if(data==NULL || data->type!=ACTION_STATEMENT_NODE) return TRUE; + + ID=data->ID; + if(ID<0 || ID>=m_NumActions) return TRUE; + + desc=GetActionDesc(ID); + if(desc==NULL) return TRUE; + + // Get the first child, if one exists + child_node=m_ScriptTree.GetChildItem(node); + + // Make a copy of description (so null chars can be added) + desc_copy=(char *)mem_malloc(strlen(desc)+1); + if(desc_copy==NULL) { + MessageBox("ERROR: Out of memory in ValidateActionNode()!","Out of Memory Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + strcpy(desc_copy,desc); + + // Parse the description, adding default parameter nodes appropriately + int j=0; + bool start_block_found=FALSE; + bool type_delim_found=FALSE; + char *param_name=FALSE; + int param_type_char=-1; + int param_type; + bool modified=FALSE; + + while(desc_copy[j]!='\0') { + + if(desc_copy[j]=='[') { // Note the start of a parameter block + start_block_found=TRUE; + } + else if(desc_copy[j]==':' && start_block_found) { // Note the end of parameter type field + type_delim_found=TRUE; + } + else if(desc_copy[j]==']') { // If end of block, add the parameter + + if(param_type_char!=-1 && param_name!=NULL) { + + desc_copy[j]='\0'; // mark the end of the variable name + + // Get the parameter type + param_type=ConvertParamCharToType(param_type_char); + + // Check the corresponding param (if it exists) and make it match up + if(ConformParamNode(node,child_node,param_type,param_name)) + modified=TRUE; + + if(child_node!=NULL) child_node=m_ScriptTree.GetNextSiblingItem(child_node); + } + + start_block_found=FALSE; + type_delim_found=FALSE; + param_name=FALSE; + param_type_char=-1; + } + else if(start_block_found && param_type_char==-1) { + param_type_char=desc_copy[j]; + } + else if(type_delim_found && param_name==NULL) { + param_name=&desc_copy[j]; + } + + j++; + } + + // Free up the copy memory + mem_free(desc_copy); + + // Delete any remaining child parameter nodes (they are no longer used) + if(child_node!=NULL) { + do { + HTREEITEM temp_node=child_node; + child_node=m_ScriptTree.GetNextSiblingItem(child_node); + FreeTreeItem(temp_node); + } while(child_node!=NULL); + + modified=TRUE; + } + + if(modified) + ScriptFileParseError(MODIFIED_FUNC_ERR,linenum,GetScriptID(node),GetActionFunc(ID)); + + return (!modified); +} +*/ + +// Checks the given param node (if it exists) and makes it match up with the given data +// Returns TRUE if a significant modification had to take place, FALSE otherwise +bool CDallasMainDlg::ConformParamNode(HTREEITEM parent_node, HTREEITEM ¶m_node, int type, char *name, char *def_value/*=NULL*/) +{ + tTreeNodeData *data; + CString query_ret_name; + int index; + + if(parent_node==NULL) return FALSE; + + // If the param node doesn't exist, then we need to add a default param + if(param_node==NULL) { + CreateDefaultParameterNode(parent_node,TVI_LAST,type,name,def_value); + return TRUE; + } + + // See if the node matches the given data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(param_node); + if(data!=NULL) { + // Check parameter node + if(data->type==PARAMETER_NODE && data->ID==type) { + // node matches, so copy over the name in case it's changed (not considered a major mod) + strcpy(data->name,name); + UpdateNodeText(param_node); + return FALSE; + } + + // If it's a SPECNAME, see if we can transfer it over + if(data->type==PARAMETER_NODE && data->ID==SPECNAME_PARAMETER_TYPE) { + if(type==PATH_PARAMETER_TYPE) { + data->ID=type; + strcpy(data->name,name); + index=osipf_FindPathName(data->str_val); + if(index<0) { + data->int_val=NOT_SPECIFIED_TYPE; + strcpy(data->str_val,""); + UpdateNodeText(param_node); + return TRUE; + } + data->int_val=index; + strcpy(data->str_val,GamePaths[index].name); + UpdateNodeText(param_node); + return FALSE; + } + else if(type==MATCEN_PARAMETER_TYPE) { + data->ID=type; + strcpy(data->name,name); + data->subID=USE_MATCEN_VALUE; + index=osipf_FindMatcenName(data->str_val); + if(index<0) { + data->int_val=NOT_SPECIFIED_TYPE; + strcpy(data->str_val,""); + UpdateNodeText(param_node); + return TRUE; + } + char matcen_name[MAX_MATCEN_NAME_LEN+1]; + Matcen[index]->GetName(matcen_name); + data->int_val=index; + strcpy(data->str_val,matcen_name); + UpdateNodeText(param_node); + return FALSE; + } + else if(type==LEVEL_GOAL_PARAMETER_TYPE) { + data->ID=type; + strcpy(data->name,name); + data->subID=USE_LEVEL_GOAL_VALUE; + index=osipf_FindLevelGoalName(data->str_val); + if(index<0) { + data->int_val=NOT_SPECIFIED_TYPE; + strcpy(data->str_val,""); + UpdateNodeText(param_node); + return TRUE; + } + data->int_val=index; + UpdateNodeText(param_node); + return FALSE; + } + else if(type==STRM_AUDIO_PARAMETER_TYPE) { + data->ID=type; + strcpy(data->name,name); + if(!GamefileExists(data->str_val)) { + strcpy(data->str_val,""); + UpdateNodeText(param_node); + return TRUE; + } + UpdateNodeText(param_node); + return FALSE; + } + } + + // Check query node + if(data->type==EXPRESSION_NODE && GetQueryReturnType(data->ID,query_ret_name)==type) { + // node matches, so copy over the name in case it's changed (not considered a major mod) + strcpy(data->name,name); + UpdateNodeText(param_node); + return FALSE; + } + } + + // Since the param node doesn't match up with the data, replace it with a default that does + HTREEITEM new_node; + new_node=CreateDefaultParameterNode(parent_node,param_node,type,name,def_value); + FreeTreeItem(param_node); + param_node=new_node; + UpdateNodeText(param_node); + + return TRUE; +} + + +// Validates a query node by conforming its parameters to what they should be +// returns FALSE if node was modified significantly, otherwise TRUE +bool CDallasMainDlg::ValidateQueryNode(HTREEITEM node, int linenum) +{ + CString name_text, default_text, range_text; + tTreeNodeData *data; + HTREEITEM child_node; + int ID; + char *desc; + + if(node==NULL) return TRUE; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); + if(data==NULL || data->type!=EXPRESSION_NODE) return TRUE; + + ID=data->ID; + if(ID<0 || ID>=m_NumQueries) return TRUE; + + desc=strchr(GetQueryDesc(ID),':'); + if(desc==NULL) return TRUE; + desc++; + + // Get the first child, if one exists + child_node=m_ScriptTree.GetChildItem(node); + + // Parse the description, adding default parameter nodes appropriately + bool modified=FALSE; + while((*desc)!='\0') { + + if((*desc)=='[') { // Note the start of a parameter block + + int param_type=ParseParamBlock(desc,name_text,default_text,range_text); + if(param_type>=0) { + + // Check the corresponding param (if it exists) and make it match up + if(ConformParamNode(node,child_node,param_type,name_text.GetBuffer(0),default_text.GetBuffer(0))) + modified=TRUE; + + if(child_node!=NULL) child_node=m_ScriptTree.GetNextSiblingItem(child_node); + } + } + else { + desc++; + } + } + + // Delete any remaining child parameter nodes (they are no longer used) + if(child_node!=NULL) { + do { + HTREEITEM temp_node=child_node; + child_node=m_ScriptTree.GetNextSiblingItem(child_node); + FreeTreeItem(temp_node); + } while(child_node!=NULL); + + modified=TRUE; + } + + if(modified) + ScriptFileParseError(MODIFIED_FUNC_ERR,linenum,GetScriptID(node),GetQueryFunc(ID)); + + return (!modified); +} + +/* OLD VERSION +// Validates a query node by conforming its parameters to what they should be +// returns FALSE if node was modified significantly, otherwise TRUE +bool CDallasMainDlg::ValidateQueryNode(HTREEITEM node, int linenum) +{ + tTreeNodeData *data; + HTREEITEM child_node; + int ID; + char *desc, *desc_copy; + + if(node==NULL) return TRUE; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); + if(data==NULL || data->type!=EXPRESSION_NODE) return TRUE; + + ID=data->ID; + if(ID<0 || ID>=m_NumQueries) return TRUE; + + desc=strchr(GetQueryDesc(ID),':'); + if(desc==NULL) return TRUE; + desc++; + + // Get the first child, if one exists + child_node=m_ScriptTree.GetChildItem(node); + + // Make a copy of description (so null chars can be added) + desc_copy=(char *)mem_malloc(strlen(desc)+1); + if(desc_copy==NULL) { + MessageBox("ERROR: Out of memory in ValidateQueryNode()!","Out of Memory Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + strcpy(desc_copy,desc); + + // Parse the description, adding default parameter nodes appropriately + int j=0; + bool start_block_found=FALSE; + bool type_delim_found=FALSE; + char *param_name=FALSE; + int param_type_char=-1; + int param_type; + bool modified=FALSE; + + while(desc_copy[j]!='\0') { + + if(desc_copy[j]=='[') { // Note the start of a parameter block + start_block_found=TRUE; + } + else if(desc_copy[j]==':' && start_block_found) { // Note the end of parameter type field + type_delim_found=TRUE; + } + else if(desc_copy[j]==']') { // If end of block, add the parameter + + if(param_type_char!=-1 && param_name!=NULL) { + + desc_copy[j]='\0'; // mark the end of the variable name + + // Get the parameter type + param_type=ConvertParamCharToType(param_type_char); + + // Check the corresponding param (if it exists) and make it match up + if(ConformParamNode(node,child_node,param_type,param_name)) + modified=TRUE; + + if(child_node!=NULL) child_node=m_ScriptTree.GetNextSiblingItem(child_node); + } + + start_block_found=FALSE; + type_delim_found=FALSE; + param_name=FALSE; + param_type_char=-1; + } + else if(start_block_found && param_type_char==-1) { + param_type_char=desc_copy[j]; + } + else if(type_delim_found && param_name==NULL) { + param_name=&desc_copy[j]; + } + + j++; + } + + // Free up the copy memory + mem_free(desc_copy); + + // Delete any remaining child parameter nodes (they are no longer used) + if(child_node!=NULL) { + do { + HTREEITEM temp_node=child_node; + child_node=m_ScriptTree.GetNextSiblingItem(child_node); + FreeTreeItem(temp_node); + } while(child_node!=NULL); + + modified=TRUE; + } + + if(modified) + ScriptFileParseError(MODIFIED_FUNC_ERR,linenum,GetScriptID(node),GetQueryFunc(ID)); + + return (!modified); +} +*/ + +// Fills up the given menu with the categories of actions +// NOTE: Command ID's of menu items start at the given command_offset +void CDallasMainDlg::FillActionMenu(CMenu *action_menu, int command_offset) +{ + int j,k, actions_added; + + // Loop through the categories, creating submenu for each one + for(j=0;jAppendMenu(MF_POPUP|MF_GRAYED, (unsigned int)category_submenu.Detach(), m_FunctionCategories[j]); + else + action_menu->AppendMenu(MF_POPUP, (unsigned int)category_submenu.Detach(), m_FunctionCategories[j]); + } +} + + +// Fills up the given menu with the categories of queries +// NOTE: Command ID's of menu items start at the given command_offset +void CDallasMainDlg::FillQueryMenu(CMenu *query_menu, int command_offset, int valid_return_type, char *valid_return_name) +{ + int j,k, queries_added; + int query_ret_type; + CString query_ret_name; + bool types_match; + + // Loop through the categories, creating submenu for each one + for(j=0;jAppendMenu(MF_POPUP|MF_GRAYED, (unsigned int)category_submenu.Detach(), m_FunctionCategories[j]); + else + query_menu->AppendMenu(MF_POPUP, (unsigned int)category_submenu.Detach(), m_FunctionCategories[j]); + } +} + + +// Attempts to parse the Nth (indexed at 1) bracketed section of the given function node's desc, +// and obtain from it the parameter name, default string, and range string. +// It returns the param type if successfull, or -1 if the requested Parameter section +// does not exist +int CDallasMainDlg::ParseNthParam(HTREEITEM func_node, int n, CString &name_text, CString &default_text, CString &range_text) +{ + tTreeNodeData *data; + + if(func_node==NULL) return(-1); + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(func_node); + if(data==NULL) return(-1); + + // Handle action nodes + if(data->type==ACTION_STATEMENT_NODE) { + char *desc=GetActionDesc(data->ID); + return(ParseNthParam(desc,n,name_text,default_text,range_text)); + } + + // Handle query nodes + if(data->type==EXPRESSION_NODE) { + char *desc=GetQueryDesc(data->ID); + return(ParseNthParam(desc,n,name_text,default_text,range_text)); + } + + return(-1); +} + + +// Attempts to parse the Nth (indexed at 1) bracketed section of the given action desc, +// and obtain from it the parameter name, default string, and range string. +// It returns the param type if successfull, or -1 if the requested Parameter section +// does not exist +int CDallasMainDlg::ParseNthParam(char *desc, int n, CString &name_text, CString &default_text, CString &range_text) +{ + // Check validity of desc and given n + if(n<=0 || desc==NULL) return(-1); + + // Find the n'th parameter block (bracketed section) + char *s; + s=strchr(desc,'['); + for(int j=1;j=range_start && value<=range_end) value_in_range=TRUE; + } + num_text=""; + range_start=0; + range_end=0; + currently_parsing=RANGE_START_NUM; + } + else if(ch=='|') { + currently_parsing=RANGE_END_NUM; + range_start=atoi(num_text.GetBuffer(0)); + num_text=""; + } + else { + num_text+=ch; + } + + range_desc++; + } + + // Check the last value range + if(currently_parsing==RANGE_START_NUM) { + range_start=atoi(num_text.GetBuffer(0)); + if(value==range_start) value_in_range=TRUE; + } + else { + range_end=atoi(num_text.GetBuffer(0)); + if(value>=range_start && value<=range_end) value_in_range=TRUE; + } + + return(value_in_range); +} + + +// Returns TRUE if the given float is in the given range, FALSE otherwise +bool CDallasMainDlg::VerifyFloatRange(float value, char *range_desc) +{ + CString num_text; + float range_start=0.0, range_end=0.0; + + bool value_in_range=FALSE; + int currently_parsing=RANGE_START_NUM; + while((*range_desc)!='\0') { + + char ch=(*range_desc); + if(ch==',') { + if(currently_parsing==RANGE_START_NUM) { + range_start=atof(num_text.GetBuffer(0)); + if(value==range_start) value_in_range=TRUE; + } + else { + range_end=atof(num_text.GetBuffer(0)); + if(value>=range_start && value<=range_end) value_in_range=TRUE; + } + num_text=""; + range_start=0.0; + range_end=0.0; + currently_parsing=RANGE_START_NUM; + } + else if(ch=='|') { + currently_parsing=RANGE_END_NUM; + range_start=atof(num_text.GetBuffer(0)); + num_text=""; + } + else { + num_text+=ch; + } + + range_desc++; + } + + // Check the last value range + if(currently_parsing==RANGE_START_NUM) { + range_start=atof(num_text.GetBuffer(0)); + if(value==range_start) value_in_range=TRUE; + } + else { + range_end=atof(num_text.GetBuffer(0)); + if(value>=range_start && value<=range_end) value_in_range=TRUE; + } + + return(value_in_range); +} + + +///////////////////////////////////////////////////////////////////////////// +// Script Grouping Functions +///////////////////////////////////////////////////////////////////////////// + + +// Initializes the script grouping list for use +void CDallasMainDlg::InitScriptGroupingList(void) +{ + m_ScriptGroupingList=NULL; + m_NumScriptGroups=0; +} + + +// Deletes memory allocated for the Script Grouping list +void CDallasMainDlg::ClearScriptGroupingList(void) +{ + int j,k; + + // Free up all the individual script node lists + for(j=0;jnum_script_nodes > 0) { + mem_free(event_section->script_node_list); + event_section->script_node_list=NULL; + event_section->num_script_nodes=0; + } + } + } + + // Free up the entire script grouping list + if(m_NumScriptGroups>0) { + mem_free(m_ScriptGroupingList); + m_ScriptGroupingList=NULL; + m_NumScriptGroups=0; + } +} + + +// Adds the node into the appropriate event section of the owner group +int CDallasMainDlg::AddNodeToScriptOwnerGroup(int pos, HTREEITEM script_node) +{ + HTREEITEM event_node; + tTreeNodeData *event_data; + int event_type; + + // Make sure pos is valid + if(pos<0 || pos>=m_NumScriptGroups) return FALSE; + + // Get the event type + event_node=GetScriptEventNode(script_node); + if(event_node==NULL) return FALSE; + event_data=(tTreeNodeData *)m_ScriptTree.GetItemData(event_node); + if(event_data==NULL) return FALSE; + event_type=event_data->ID; + + // Make sure event type is valid + if(event_type<0 || event_type>=MAX_EVENT_TYPES) return FALSE; + + tEventSection *event_section=&m_ScriptGroupingList[pos].event_sections[event_type]; + + // Add this node to the appropriate event section list + if(event_section->num_script_nodes==0) + event_section->script_node_list=(HTREEITEM *)mem_malloc(sizeof(HTREEITEM)*1); + else + event_section->script_node_list=(HTREEITEM *)mem_realloc(event_section->script_node_list,sizeof(HTREEITEM)*(event_section->num_script_nodes+1)); + + if(event_section->script_node_list==NULL) return FALSE; + event_section->num_script_nodes++; + + int new_pos=event_section->num_script_nodes-1; + event_section->script_node_list[new_pos]=script_node; + + return TRUE; +} + + +// Categorizes the given node into the grouping list +int CDallasMainDlg::AddNodeToScriptGroupingList(HTREEITEM script_node) +{ + HTREEITEM owner_node; + tTreeNodeData *data, *owner_data; + int j; + + // Make sure it's a script header node + data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_node); + if(data==NULL || data->type!=SCRIPT_HEADER_NODE) return FALSE; + + // Get the owner node data + owner_node=GetScriptOwnerNode(script_node); + if(owner_node==NULL) return FALSE; + owner_data=(tTreeNodeData *)m_ScriptTree.GetItemData(owner_node); + if(owner_data==NULL) return FALSE; + + // Search the grouping list for a matching owner group + for(j=0;jID) continue; + + // If it's not a LEVEL owner, we need to make sure the handles also match + if(m_ScriptGroupingList[j].owner_type != LEVEL_TYPE) { + if(m_ScriptGroupingList[j].owner_handle != owner_data->int_val) continue; + } + + return(AddNodeToScriptOwnerGroup(j,script_node)); + } + + // Since owner does not exist, create a new Script Group entry + if(m_NumScriptGroups==0) + m_ScriptGroupingList=(tScriptOwnerGroup *)mem_malloc(sizeof(tScriptOwnerGroup)*1); + else + m_ScriptGroupingList=(tScriptOwnerGroup *)mem_realloc(m_ScriptGroupingList,sizeof(tScriptOwnerGroup)*(m_NumScriptGroups+1)); + + if(m_ScriptGroupingList==NULL) return FALSE; + m_NumScriptGroups++; + + // Initialize the new entry + int new_pos=m_NumScriptGroups-1; + m_ScriptGroupingList[new_pos].owner_type=owner_data->ID; + m_ScriptGroupingList[new_pos].owner_handle=owner_data->int_val; + for(j=0;j=m_NumScriptGroups) return(name.GetBuffer(0)); + + tScriptOwnerGroup *owner_group=&m_ScriptGroupingList[pos]; + + switch(owner_group->owner_type) { + case OBJECT_TYPE: + name.Format("ID_CUSTOM_OBJECT_%04X",owner_group->owner_handle); + break; + case TRIGGER_TYPE: + name.Format("ID_TRIGGER_%04X",owner_group->owner_handle); + break; + case LEVEL_TYPE: + name.Format("%s",LEVEL_ID_NAME); + break; + default: + name.Format("ID_ILLEGAL_SCRIPT_TYPE"); + break; + } + + return(name.GetBuffer(0)); +} + + +// Creates a Class name for a given owner node +char *CDallasMainDlg::CreateScriptClassName(int pos) +{ + static CString name=""; + + if(pos<0 || pos>=m_NumScriptGroups) return(name.GetBuffer(0)); + + tScriptOwnerGroup *owner_group=&m_ScriptGroupingList[pos]; + + switch(owner_group->owner_type) { + case OBJECT_TYPE: + name.Format("CustomObjectScript_%04X",owner_group->owner_handle); + break; + case TRIGGER_TYPE: + name.Format("TriggerScript_%04X",owner_group->owner_handle); + break; + case LEVEL_TYPE: + name.Format("%s",LEVEL_CLASS_NAME); + break; + default: + name.Format("IllegalScriptType"); + break; + } + + return(name.GetBuffer(0)); +} + + +// Creates a Class name for a given owner node +char *CDallasMainDlg::CreateScriptGlobalCtrName(int ID) +{ + static CString name=""; + + if(ID<0) return(name.GetBuffer(0)); + + name.Format("ScriptActionCtr_%03d",ID); + + return(name.GetBuffer(0)); +} + + +///////////////////////////////////////////////////////////////////////////// +// Parsing Functions +///////////////////////////////////////////////////////////////////////////// + +CString CurrentParsingFilename=""; + +// Handle Parse Errors +void CDallasMainDlg::ScriptFileParseError(int error_code, int linenum, int script_ID, char *name) +{ + CString err_msg; + + switch(error_code) { + case UEOS_ERR: + err_msg.Format("ERROR: Unexpected end of file while parsing %s, line %d.",CurrentParsingFilename.GetBuffer(0),linenum); + break; + case INVALID_FUNC_ERR: + err_msg.Format( + "ERROR: An invalid glue function name (%s) was encountered in %s, line %d.\n\n" + "Hence, Script #%d now contains an invalid action or query that must be replaced.", + name,CurrentParsingFilename.GetBuffer(0),linenum,script_ID); + break; + case INVALID_NODE_ERR: + err_msg.Format( + "ERROR: An invalid script node was encountered in %s, line %d.\n\n." + "Because this node could not be added, one or more of your scripts may be corrupt.", + CurrentParsingFilename.GetBuffer(0),linenum); + break; + case MODIFIED_FUNC_ERR: + err_msg.Format( + "ERROR: A glue function (%s) with out of date parameters was encountered in %s, line %d.\n\n" + "Hence, Script #%d now contains an action or query that may need to be modified.", + name,CurrentParsingFilename.GetBuffer(0),linenum,script_ID); + break; + case INVALID_MSGID_ERR: + err_msg.Format( + "ERROR: An invalid Message ID (%s) was encountered in %s, line %d.\n\n" + "Hence, Script #%d now contains a Message ID that needs to be replaced.", + name,CurrentParsingFilename.GetBuffer(0),linenum,script_ID); + break; + default: + err_msg.Format("ERROR: An unknown error was detected in %s, line %d",CurrentParsingFilename.GetBuffer(0),linenum); + break; + } + + MessageBox(err_msg,"Script File Parse Error",MB_OK|MB_ICONEXCLAMATION); +} + + +// Reads in the script source file and calls the various parsers for the +// Appropriate sections +int CDallasMainDlg::ParseSourceScript(char *filename) +{ + CFILE *infile; + char linebuf[2048]; + char tempbuf[256]; + char *line; + int linenum; + int valid_lines_read, version; + char fullpath[_MAX_PATH]; + int rc; + + HTREEITEM last_node_added, current_parent, returned_node; + bool skip_children; + int skip_depth; + bool last_node_childless; + + CurrentParsingFilename=m_ScriptFilename; + + ddio_MakePath(fullpath,LocalScriptDir,filename,NULL); + + // Try to open the file for loading + infile=cfopen (fullpath,"rt"); + if (!infile) + { + CString msg; + msg.Format("Unable to open \"%s\"!",filename); + MessageBox(msg,"No Script Source File Found!",MB_OK|MB_ICONEXCLAMATION); + + // Clear out the Script Tree + ClearTree(); + + // Add the clipboard node + CreateDefaultClipboardNode(); + + return FALSE; + } + + linenum=0; + + // Read in and parse each line of the file + while (!cfeof(infile)) { + + // Clear the buffer + strcpy(linebuf,""); + + // Read in a line from the file + cf_ReadString(linebuf, sizeof(linebuf), infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + // Check for Start of Script Block Section + if (strncmp(line,SCRIPT_BLOCK_START_TAG,strlen(SCRIPT_BLOCK_START_TAG)) == 0) { + bool done = false; + + // Clear out the Script Tree + ClearTree(); + + // Clear out the name lists + ClearNameLists(); + + // Set valid line counter to track whether we're reading header info or tree nodes + valid_lines_read=0; + + // Set tree node trackers so we know where we are in the actual tree + last_node_added=NULL; + current_parent=TVI_ROOT; + + // Set variables that allow child nodes to be skipped over + // when a bad Action or Query node is read in (invalid function name) + skip_children=FALSE; + skip_depth=0; + last_node_childless=FALSE; + + // Read all the lines in the block + while (!done && !cfeof(infile)) { + + strcpy(linebuf,""); + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + // If it's an empty line or a comment, skip it + if(strlen(line)==0 || strncmp(line,"//",2)==0) + continue; + + // Check for End of Script Block Section + if (strncmp(line,SCRIPT_BLOCK_END_TAG,strlen(SCRIPT_BLOCK_END_TAG)) == 0) { + done=true; + continue; + } + + // Check for Start of User Type values + if (strncmp(line,USERTYPE_VALS_START_TAG,strlen(USERTYPE_VALS_START_TAG))==0) { // Parse a user type block + tEnumDBEntry *enum_entry; + char *enum_name; + int DBslot; + bool end_of_usertype_found; + + enum_entry=NULL; + + // Strip off the name of this enumeration type + enum_name=strtok(line,WHITESPACE_CHARS); + if(enum_name!=NULL) enum_name=strtok(NULL,""); + if(enum_name!=NULL && (DBslot=GetEnumID(enum_name))!=INVALID_ENUM) { + enum_entry = &m_EnumDatabase[DBslot]; + } + + // Parse the enumeration values for this user type + end_of_usertype_found = FALSE; + do { + + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,USERTYPE_VALS_END_TAG,strlen(USERTYPE_VALS_END_TAG)) == 0) + end_of_usertype_found = TRUE; + else if(enum_entry!=NULL) { + tEnumValueEntry *value_entry; + int enum_value; + char *enum_value_string; + char *enum_value_name; + + // Parse out the enum value and value name + enum_value_string=strtok(line,":"); + if(enum_value_string!=NULL) { + enum_value=atoi(enum_value_string); + enum_value_name=strtok(NULL,""); + } + + if(enum_value_string==NULL || enum_value_name==NULL || GetEnumValueName(enum_entry->name,enum_value)!=NULL) { + value_entry = NULL; + } + else if(enum_entry->num_values>=MAX_ENUM_VALUES || enum_entry->num_values>=(enum_entry->max_values+2)) { + value_entry = NULL; + } + else { + value_entry = &enum_entry->values[enum_entry->num_values++]; + value_entry->name = (char *) mem_malloc(strlen(enum_value_name)+1); + if(value_entry->name == NULL) { + FunctionFileParseError(NO_MEM_ERR,linenum,filename); + cfclose(infile); + return FALSE; + } + strcpy(value_entry->name,enum_value_name); + value_entry->value=enum_value; + } + } + + } while (!end_of_usertype_found && !cfeof(infile)); + + continue; + } + + // Check for Door List Block, and read it in + if (strncmp(line,DOOR_LIST_START_TAG,strlen(DOOR_LIST_START_TAG)) == 0) { + bool end_list_found = 0; + do { + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,DOOR_LIST_END_TAG,strlen(DOOR_LIST_END_TAG)) == 0) + end_list_found=TRUE; + else if(strlen(line)>0) + AddDoorToList(line); + + } while (!end_list_found && !cfeof(infile)); + + continue; + } + + // Check for Object List Block, and read it in + if (strncmp(line,OBJECT_LIST_START_TAG,strlen(OBJECT_LIST_START_TAG)) == 0) { + bool end_list_found = 0; + do { + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,OBJECT_LIST_END_TAG,strlen(OBJECT_LIST_END_TAG)) == 0) + end_list_found=TRUE; + else if(strlen(line)>0) + AddObjectToList(line); + + } while (!end_list_found && !cfeof(infile)); + + continue; + } + + // Check for Room List Block, and read it in + if (strncmp(line,ROOM_LIST_START_TAG,strlen(ROOM_LIST_START_TAG)) == 0) { + bool end_list_found = 0; + do { + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,ROOM_LIST_END_TAG,strlen(ROOM_LIST_END_TAG)) == 0) + end_list_found=TRUE; + else if(strlen(line)>0) + AddRoomToList(line); + + } while (!end_list_found && !cfeof(infile)); + + continue; + } + + // Check for Trigger List Block, and read it in + if (strncmp(line,TRIGGER_LIST_START_TAG,strlen(TRIGGER_LIST_START_TAG)) == 0) { + bool end_list_found = 0; + do { + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,TRIGGER_LIST_END_TAG,strlen(TRIGGER_LIST_END_TAG)) == 0) + end_list_found=TRUE; + else if(strlen(line)>0) + AddTriggerToList(line); + + } while (!end_list_found && !cfeof(infile)); + + continue; + } + + // Check for Sound List Block, and read it in + if (strncmp(line,SOUND_LIST_START_TAG,strlen(SOUND_LIST_START_TAG)) == 0) { + bool end_list_found = 0; + do { + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,SOUND_LIST_END_TAG,strlen(SOUND_LIST_END_TAG)) == 0) + end_list_found=TRUE; + else if(strlen(line)>0) + AddSoundToList(line); + + } while (!end_list_found && !cfeof(infile)); + + continue; + } + + // Check for Texture List Block, and read it in + if (strncmp(line,TEXTURE_LIST_START_TAG,strlen(TEXTURE_LIST_START_TAG)) == 0) { + bool end_list_found = 0; + do { + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,TEXTURE_LIST_END_TAG,strlen(TEXTURE_LIST_END_TAG)) == 0) + end_list_found=TRUE; + else if(strlen(line)>0) + AddTextureToList(line); + + } while (!end_list_found && !cfeof(infile)); + + continue; + } + + // Check for Specname List Block, and read it in + if (strncmp(line,SPECNAME_LIST_START_TAG,strlen(SPECNAME_LIST_START_TAG)) == 0) { + bool end_list_found = 0; + do { + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,SPECNAME_LIST_END_TAG,strlen(SPECNAME_LIST_END_TAG)) == 0) + end_list_found=TRUE; + else if(strlen(line)>0) + AddSpecnameToList(line); + + } while (!end_list_found && !cfeof(infile)); + + continue; + } + + // Check for Path List Block, and read it in + if (strncmp(line,PATH_LIST_START_TAG,strlen(PATH_LIST_START_TAG)) == 0) { + bool end_list_found = 0; + do { + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,PATH_LIST_END_TAG,strlen(PATH_LIST_END_TAG)) == 0) + end_list_found=TRUE; + else if(strlen(line)>0) + AddPathToList(line); + + } while (!end_list_found && !cfeof(infile)); + + continue; + } + + // Check for Matcen List Block, and read it in + if (strncmp(line,MATCEN_LIST_START_TAG,strlen(MATCEN_LIST_START_TAG)) == 0) { + bool end_list_found = 0; + do { + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,MATCEN_LIST_END_TAG,strlen(MATCEN_LIST_END_TAG)) == 0) + end_list_found=TRUE; + else if(strlen(line)>0) + AddMatcenToList(line); + + } while (!end_list_found && !cfeof(infile)); + + continue; + } + + // Check for Goal List Block, and read it in + if (strncmp(line,GOAL_LIST_START_TAG,strlen(GOAL_LIST_START_TAG)) == 0) { + bool end_list_found = 0; + do { + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,GOAL_LIST_END_TAG,strlen(GOAL_LIST_END_TAG)) == 0) + end_list_found=TRUE; + else if(strlen(line)>0) + AddGoalToList(line); + + } while (!end_list_found && !cfeof(infile)); + + continue; + } + + // Check for StrmAudio List Block, and read it in + if (strncmp(line,STRM_AUDIO_LIST_START_TAG,strlen(STRM_AUDIO_LIST_START_TAG)) == 0) { + bool end_list_found = 0; + do { + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + if (strncmp(line,STRM_AUDIO_LIST_END_TAG,strlen(STRM_AUDIO_LIST_END_TAG)) == 0) + end_list_found=TRUE; + else if(strlen(line)>0) + AddStrmAudioToList(line); + + } while (!end_list_found && !cfeof(infile)); + + continue; + } + + // Is it the start of a child block? + if(strncmp(line,CHILD_BLOCK_START_TAG,strlen(CHILD_BLOCK_START_TAG)) == 0) { + last_node_childless=FALSE; + if(!skip_children) { + current_parent=last_node_added; + if(current_parent==NULL) current_parent=TVI_ROOT; + } + else { + skip_depth++; + } + continue; + } + + // Handles Validation of childless function nodes + if(last_node_added!=NULL && last_node_childless) { + ValidateFunctionNode(last_node_added,linenum); + + // Need this to update node text that depends on subnodes + UpdateNodeText(last_node_added); + + last_node_childless=FALSE; + } + + // Is it the end of a child block? + if(strncmp(line,CHILD_BLOCK_END_TAG,strlen(CHILD_BLOCK_END_TAG)) == 0) { + if(!skip_children || skip_depth<=0) { + + skip_children=FALSE; + skip_depth=0; + + last_node_added=current_parent; + if(last_node_added==TVI_ROOT) + last_node_added=NULL; + else { + // Need this to validate a function node once all of its params have been added + ValidateFunctionNode(last_node_added,linenum); + + // Need this to update node text that depends on subnodes + UpdateNodeText(last_node_added); + } + + if(current_parent!=TVI_ROOT) + current_parent=m_ScriptTree.GetParentItem(current_parent); + if(current_parent==NULL) current_parent=TVI_ROOT; + } + else + skip_depth--; + + continue; + } + + // If we're skipping children, but the depth is still zero here, + // then must not be any children to skip! + if(skip_children && skip_depth<=0) { + skip_children=FALSE; + skip_depth=0; + } + + // See if it should be the save version line + if(valid_lines_read==0) { + rc=sscanf(line,"%s %d",tempbuf,&version); + if(rc==2 && strcmp(tempbuf,"VERSION")==0) + valid_lines_read++; + continue; + } + + // See if it should be the next script ID line + if(valid_lines_read==1) { + rc=sscanf(line,"%s %d",tempbuf,&m_NextScriptID); + if(rc==2 && strcmp(tempbuf,"NEXT_ID")==0) + valid_lines_read++; + continue; + } + + // It must be a node then, + // so (if we're not skipping children) parse it and add it to the tree + if(!skip_children) { + if(version>=1) + returned_node=ParseScriptNodeLine_v1U(line,linenum,current_parent,skip_children,version); + else + returned_node=ParseScriptNodeLine_v0(line,linenum,current_parent,skip_children); + + if(returned_node!=NULL ) { + last_node_added=returned_node; + last_node_childless=TRUE; + UpdateNodeText(last_node_added); + } + else + ScriptFileParseError(INVALID_NODE_ERR,linenum,0,NULL); + + if(returned_node==NULL || skip_children) { + skip_children=TRUE; + skip_depth=0; + } + } + } + + if (!done) + ScriptFileParseError(UEOS_ERR,linenum,0,NULL); + } + } + + cfclose(infile); + + // Add the clipboard node + CreateDefaultClipboardNode(); + + return TRUE; +} + + +// VERSION 0: Parses a script node line, and if it's valid, adds it to the given parent +HTREEITEM CDallasMainDlg::ParseScriptNodeLine_v0(char *line, int linenum, HTREEITEM parent, bool &skip_all_children, HTREEITEM insert_before/*=TVI_LAST*/) +{ + tTreeNodeData node_data; + bool add_node; + int index; + + // Make sure given data is ok + if(line==NULL || parent==NULL || skip_all_children) return NULL; + + // Read in the node type + line=strtok(line,":"); + if(line==NULL) return NULL; + node_data.type=atoi(line); + + // Read in the rest of this node's data + add_node=FALSE; + switch(node_data.type) { + case SCRIPT_HEADER_NODE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.ID=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case SCRIPT_OWNER_NODE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.ID=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.int_val=atoi(line); + + // Verify object name + if(node_data.ID==OBJECT_TYPE) { + object *objp=ObjGet(node_data.int_val); + if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { + node_data.int_val=OBJECT_HANDLE_NONE; + strcpy(node_data.str_val,""); + } + else { + strcpy(node_data.str_val,objp->name); + } + } + + // Verify trigger name + if(node_data.ID==TRIGGER_TYPE) { + int t=node_data.int_val; + if(t<0 || t>=Num_triggers || t>=MAX_NAMED_TRIGGERS || strlen(Triggers[t].name)==0) { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + } + else { + strcpy(node_data.str_val,Triggers[t].name); + } + } + + add_node=TRUE; + break; + case SCRIPT_EVENT_NODE: + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.ID=atoi(line); + add_node=TRUE; + break; + case CONDITIONAL_HEADER_NODE: + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.ID=atoi(line); + add_node=TRUE; + break; + case ACTIONS_HEADER_NODE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.ID=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.subID=atoi(line); + add_node=TRUE; + break; + case CONDITIONAL_STATEMENT_NODE: + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.ID=atoi(line); + add_node=TRUE; + break; + case EXPRESSION_NODE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.ID=GetQueryFuncID(line); + if(node_data.ID==INVALID_FUNCTION_ID) { + ScriptFileParseError(INVALID_FUNC_ERR,linenum,GetScriptID(parent),line); + skip_all_children=TRUE; + } + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case EXPRESSION_OPERATOR_NODE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.ID=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.subID=atoi(line); + add_node=TRUE; + break; + case ACTION_STATEMENT_NODE: + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.ID=GetActionFuncID(line); + if(node_data.ID==INVALID_FUNCTION_ID) { + ScriptFileParseError(INVALID_FUNC_ERR,linenum,GetScriptID(parent),line); + skip_all_children=TRUE; + } + add_node=TRUE; + break; + case LOGICAL_OPERATOR_NODE: + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.ID=atoi(line); + add_node=TRUE; + break; + case PARAMETER_NODE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.ID=atoi(line); + + // Get param data based upon what kind of parameter it is + switch(node_data.ID) { + case DOOR_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.subID=atoi(line); + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + + // Verify door name + if(node_data.subID==USE_OBJECT_HANDLE) { + object *objp=ObjGet(node_data.int_val); + if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { + node_data.int_val=OBJECT_HANDLE_NONE; + strcpy(node_data.str_val,""); + } + else { + strcpy(node_data.str_val,objp->name); + } + } + + add_node=TRUE; + break; + case OBJECT_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.subID=atoi(line); + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + + // Verify object name + if(node_data.subID==USE_OBJECT_HANDLE) { + object *objp=ObjGet(node_data.int_val); + if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { + node_data.int_val=OBJECT_HANDLE_NONE; + strcpy(node_data.str_val,""); + } + else { + strcpy(node_data.str_val,objp->name); + } + } + + add_node=TRUE; + break; + case ROOM_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + + // Verify room name + index=node_data.int_val; + if(index<0 || index>Highest_room_index || !Rooms[index].used || Rooms[index].name==NULL) { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + } + else { + strcpy(node_data.str_val,Rooms[index].name); + } + + add_node=TRUE; + break; + case TRIGGER_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + + // Verify trigger name + index=node_data.int_val; + if(index<0 || index>=Num_triggers || index>=MAX_NAMED_TRIGGERS || strlen(Triggers[index].name)==0) { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + } + else { + strcpy(node_data.str_val,Triggers[index].name); + } + + add_node=TRUE; + break; + case INT_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case BOOL_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case FLOAT_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.float_val1=atof(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case VECTOR_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.float_val1=atof(line); + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.float_val2=atof(line); + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.float_val3=atof(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case STRING_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + strcpy(node_data.str_val,line); + if(FindMessageInList(line)==NULL) { + strcpy(node_data.str_val,""); + if(strcmp(line,NOT_SPECIFIED_MSG)!=0) + ScriptFileParseError(INVALID_MSGID_ERR,linenum,GetScriptID(parent),line); + } + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case PERCENTAGE_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.float_val1=atof(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case ENUM_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case SCRIPT_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case SOUND_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + index=atoi(line); + if(index<0 || index>=m_SoundListSize) + node_data.int_val=-1; + else + node_data.int_val=FindSoundName(m_SoundList[atoi(line)]); + + if(node_data.int_val<0) { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + + // Display warning message here... + } + else { + strcpy(node_data.str_val,m_SoundList[atoi(line)]); + } + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case SPECNAME_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + strcpy(node_data.str_val,line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case TEXTURE_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + index=atoi(line); + if(index<0 || index>=m_TextureListSize) + node_data.int_val=-1; + else + node_data.int_val=FindTextureName(m_TextureList[atoi(line)]); + + if(node_data.int_val<0) { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + + // Display warning message here... + } + else { + strcpy(node_data.str_val,m_TextureList[atoi(line)]); + } + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case FLAG_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case PATH_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + index=atoi(line); + if(index<0 || index>=m_PathListSize) + node_data.int_val=-1; + else + node_data.int_val=osipf_FindPathName(m_PathList[index]); + + if(node_data.int_val<0) { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + + // Display warning message here... + } + else { + strcpy(node_data.str_val,m_PathList[index]); + } + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case MATCEN_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.subID=atoi(line); + if((line=strtok(NULL,":"))==NULL) return NULL; + index=atoi(line); + if(index<0 || index>=m_MatcenListSize) + node_data.int_val=-1; + else + node_data.int_val=osipf_FindMatcenName(m_MatcenList[index]); + + if(node_data.int_val<0) { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + + // Display warning message here... + } + else { + strcpy(node_data.str_val,m_MatcenList[index]); + } + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case LEVEL_GOAL_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.subID=atoi(line); + if((line=strtok(NULL,":"))==NULL) return NULL; + index=atoi(line); + if(index<0 || index>=m_GoalListSize) + node_data.int_val=-1; + else + node_data.int_val=osipf_FindLevelGoalName(m_GoalList[index]); + + if(node_data.int_val<0) { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + + // Display warning message here... + } + else { + strcpy(node_data.str_val,m_GoalList[index]); + } + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case STRM_AUDIO_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + index=atoi(line); + if(index<0 || index>=m_StrmAudioListSize || !GamefileExists(m_StrmAudioList[index])) + strcpy(node_data.str_val,""); + else { + strcpy(node_data.str_val,m_StrmAudioList[index]); + + // Display warning message here... + } + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + default: + break; + } + break; + case PARAMETER_OPERATOR_NODE: + break; + case UNKNOWN_NODE: + break; + default: + break; + } + + if(add_node) + return(AddNodeToTree(parent,insert_before,&node_data)); + + return NULL; +} + + +// VERSION 1: Parses a script node line, and if it's valid, adds it to the given parent +HTREEITEM CDallasMainDlg::ParseScriptNodeLine_v1U(char *line, int linenum, HTREEITEM parent, bool &skip_all_children, int version, HTREEITEM insert_before/*=TVI_LAST*/) +{ + tTreeNodeData node_data; + bool add_node; + int index; + int scriptID; + + // Make sure given data is ok + if(line==NULL || parent==NULL || skip_all_children) return NULL; + + // Determine what script we're in + scriptID=-1; + if(parent!=TVI_ROOT) + scriptID=GetScriptID(parent); + + // Read in the node type + line=strtok(line,":"); + if(line==NULL) return NULL; + node_data.type=atoi(line); + + // Read in the rest of this node's data + add_node=FALSE; + switch(node_data.type) { + case SCRIPT_HEADER_NODE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.ID=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case SCRIPT_OWNER_NODE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.ID=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + index=atoi(line); + + if(node_data.ID==OBJECT_TYPE) { + if(index>=0 && index=0 && index= 0) { + strcpy(node_data.str_val,m_TriggerList[index]); + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + SpecialScriptFileParseError(linenum,scriptID,"Trigger Script Owner",m_TriggerList[index]); + } + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + } + } + else { + node_data.int_val=index; + strcpy(node_data.str_val,""); + } + + add_node=TRUE; + break; + case SCRIPT_EVENT_NODE: + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.ID=atoi(line); + add_node=TRUE; + break; + case CONDITIONAL_HEADER_NODE: + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.ID=atoi(line); + add_node=TRUE; + break; + case ACTIONS_HEADER_NODE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.ID=atoi(line); + if(version>=3) { + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + } + else { + node_data.int_val=CONTINUE_SCRIPT_CHAIN; + } + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.subID=atoi(line); + add_node=TRUE; + break; + case CONDITIONAL_STATEMENT_NODE: + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.ID=atoi(line); + add_node=TRUE; + break; + case EXPRESSION_NODE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.ID=GetQueryFuncID(line); + if(node_data.ID==INVALID_FUNCTION_ID) { + ScriptFileParseError(INVALID_FUNC_ERR,linenum,scriptID,line); + skip_all_children=TRUE; + } + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case EXPRESSION_OPERATOR_NODE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.ID=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.subID=atoi(line); + add_node=TRUE; + break; + case ACTION_STATEMENT_NODE: + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.ID=GetActionFuncID(line); + if(node_data.ID==INVALID_FUNCTION_ID) { + ScriptFileParseError(INVALID_FUNC_ERR,linenum,scriptID,line); + skip_all_children=TRUE; + } + add_node=TRUE; + break; + case LOGICAL_OPERATOR_NODE: + if((line=strtok(NULL,""))==NULL) return NULL; + node_data.ID=atoi(line); + add_node=TRUE; + break; + case PARAMETER_NODE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.ID=atoi(line); + + // Get param data based upon what kind of parameter it is + switch(node_data.ID) { + case DOOR_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.subID=atoi(line); + if((line=strtok(NULL,":"))==NULL) return NULL; + index=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + + if(node_data.subID==USE_OBJECT_HANDLE) { + if(index>=0 && index=0 && index=0 && index= 0) { + strcpy(node_data.str_val,m_RoomList[index]); + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + SpecialScriptFileParseError(linenum,scriptID,"Room",m_RoomList[index]); + } + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + } + + add_node=TRUE; + break; + case TRIGGER_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + index=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + + if(index>=0 && index= 0) { + strcpy(node_data.str_val,m_TriggerList[index]); + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + SpecialScriptFileParseError(linenum,scriptID,"Trigger",m_TriggerList[index]); + } + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + } + + add_node=TRUE; + break; + case INT_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case BOOL_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case FLOAT_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.float_val1=atof(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case VECTOR_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.float_val1=atof(line); + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.float_val2=atof(line); + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.float_val3=atof(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case STRING_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + strcpy(node_data.str_val,line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + + if(FindMessageInList(node_data.str_val)==NULL) { + if(strcmp(node_data.str_val,NOT_SPECIFIED_MSG)!=0) + ScriptFileParseError(INVALID_MSGID_ERR,linenum,scriptID,line); + strcpy(node_data.str_val,""); + } + + add_node=TRUE; + break; + case PERCENTAGE_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.float_val1=atof(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case ENUM_PARAMETER_TYPE: + if(version>=2) { + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.subID=atoi(line); + } + else { + node_data.subID=USE_ENUM_VALUE; + } + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case SCRIPT_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case SOUND_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + index=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + + if(index>=0 && index= 0) { + strcpy(node_data.str_val,m_SoundList[index]); + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + SpecialScriptFileParseError(linenum,scriptID,"Sound",m_SoundList[index]); + } + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + } + + add_node=TRUE; + break; + case SPECNAME_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + index=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + + if(index>=0 && index=0 && index= 0) { + strcpy(node_data.str_val,m_TextureList[index]); + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + SpecialScriptFileParseError(linenum,scriptID,"Texture",m_TextureList[index]); + } + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + } + + add_node=TRUE; + break; + case FLAG_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.int_val=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + add_node=TRUE; + break; + case PATH_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + index=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + + if(index>=0 && index= 0) { + strcpy(node_data.str_val,m_PathList[index]); + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + SpecialScriptFileParseError(linenum,scriptID,"Path",m_PathList[index]); + } + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + } + + add_node=TRUE; + break; + case MATCEN_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.subID=atoi(line); + if((line=strtok(NULL,":"))==NULL) return NULL; + index=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + + if(index>=0 && index= 0) { + strcpy(node_data.str_val,m_MatcenList[index]); + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + SpecialScriptFileParseError(linenum,scriptID,"Matcen",m_MatcenList[index]); + } + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + } + + add_node=TRUE; + break; + case LEVEL_GOAL_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + node_data.subID=atoi(line); + if((line=strtok(NULL,":"))==NULL) return NULL; + index=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + + if(index>=0 && index= 0) { + strcpy(node_data.str_val,m_GoalList[index]); + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + SpecialScriptFileParseError(linenum,scriptID,"Level Goal",m_GoalList[index]); + } + } + else { + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + } + + add_node=TRUE; + break; + case STRM_AUDIO_PARAMETER_TYPE: + if((line=strtok(NULL,":"))==NULL) return NULL; + index=atoi(line); + if((line=strtok(NULL,""))==NULL) return NULL; + strcpy(node_data.name,line); + + if(index>=0 && indextype==EXPRESSION_NODE) return(ValidateQueryNode(node,linenum)); + if(data->type==ACTION_STATEMENT_NODE) return(ValidateActionNode(node,linenum)); + + return TRUE; +} + + +// Reads in the message list from a file +int CDallasMainDlg::ParseMsgTableFile(char *filename) +{ + CFILE *infile; + char filebuffer[MAX_MSG_FILE_BUFFER_LEN]; + char *line, *msg_start; + int line_num; + bool next_msgid_found; + char fullpath[_MAX_PATH]; + + ddio_MakePath(fullpath,LocalScriptDir,filename,NULL); + + // Try to open the file for loading + infile=cfopen (fullpath,"rt"); + if (!infile) + { + CString msg; + msg.Format("Unable to open \"%s\"!",filename); + MessageBox(msg,"Script Message File Error!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + + line_num=0; + next_msgid_found=FALSE; + + // Read in and parse each line of the file + while (!cfeof(infile)) { + + // Clear the buffer + strcpy(filebuffer,""); + + // Read in a line from the file + cf_ReadString(filebuffer, MAX_MSG_FILE_BUFFER_LEN, infile); + line_num++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(filebuffer); + line=SkipInitialWhitespace(filebuffer); + + // If line is a comment, or empty, discard it + if(strlen(line)==0 || strncmp(line,"//",2)==0) + continue; + + if(!next_msgid_found) { // Parse out the last message ID number + + // Grab the first keyword, make sure it's valid + line=strtok(line,WHITESPACE_CHARS); + if(line==NULL || strcmp(line,NEXT_MSG_ID_NUM_KEYWORD)!=0) continue; + + // Grab the second keyword, and assign it as the next message ID + line=strtok(NULL,WHITESPACE_CHARS); + if(line==NULL) continue; + m_NextMessageID=atoi(line); + + next_msgid_found=TRUE; + } + else { // Parse line as a message line + + // Find the start of message, and mark it + msg_start=strchr(line,'='); + if(msg_start==NULL) continue; + msg_start[0]='\0'; + msg_start++; + + // Add the message to the list + AddToMessageList(line,msg_start); + } + } + + cfclose(infile); + + return TRUE; +} + + +/////////////////////////////////// +// Custom Script Block Functions +/////////////////////////////////// + + +// Initializes the data storage space +void CDallasMainDlg::InitCustomScriptStorage(void) +{ + m_CustomScriptLines=NULL; + + m_NumCustomScriptLines=0; + m_MaxNumCustomScriptLines=0; +} + + +// Clears any memory allocated for storage +void CDallasMainDlg::ClearCustomScriptStorage(void) +{ + // Clear all the lines + for(int j=0;j0) { + m_CustomScriptLines=(char **)mem_malloc(sizeof(char *)*m_MaxNumCustomScriptLines); + if(m_CustomScriptLines==NULL) { + MessageBox("ERROR: Ran out of memory allocating custom script block","Custom Script Parse Error",MB_OK|MB_ICONEXCLAMATION); + cfclose(infile); + return FALSE; + } + } + + // Read all the lines in the block + while (!done && !cfeof(infile)) { + + strcpy(linebuf,""); + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Check for End of Script Block Section + if (strncmp(linebuf,CUSTOM_SCRIPT_BLOCK_END_TAG,strlen(CUSTOM_SCRIPT_BLOCK_END_TAG)) == 0) { + done=true; + continue; + } + + // Store this line + if(m_NumCustomScriptLines < m_MaxNumCustomScriptLines) { + m_CustomScriptLines[m_NumCustomScriptLines]=(char *)mem_malloc(strlen(linebuf)+1); + if(m_CustomScriptLines[m_NumCustomScriptLines]==NULL) { + MessageBox("ERROR: Ran out of memory parsing custom script block","Custom Script Parse Error",MB_OK|MB_ICONEXCLAMATION); + cfclose(infile); + return FALSE; + } + strcpy(m_CustomScriptLines[m_NumCustomScriptLines],linebuf); + m_NumCustomScriptLines++; + } + else { + MessageBox("ERROR: The maximum custom script block line limit has been exceeded.\n\nThe excess lines will not be saved.","Custom Script Parse Error",MB_OK|MB_ICONEXCLAMATION); + done=TRUE; + } + } + + if (!done) + ScriptFileParseError(UEOS_ERR,linenum,0,NULL); + } + } + + cfclose(infile); + + return TRUE; + +} + + +// Writes out the custom script block +void CDallasMainDlg::WriteCustomScriptBlock(void) +{ + if(CurrentOutputFile==NULL) return; + + // Create the valid event case statements + O((" ")); + O(("// ===============================================================")); + O(("// Start of Custom Script Block - DO NOT EDIT ANYTHING BEFORE THIS")); + O(("// ===============================================================")); + O(("%s",CUSTOM_SCRIPT_BLOCK_START_TAG)); + + if(m_NumCustomScriptLines==0) { + O((" ")); + O(("// Enter your custom script code here")); + O((" ")); + } + else { + for(int j=0;jname,msg_data->message); + cf_WriteString(outfile,buffer.GetBuffer(0)); + } + } + + cfclose(outfile); + + return TRUE; +} + + +// Writes out a series of tabs to the CurrentOutputFile +void CDallasMainDlg::TabOver(void) +{ + int j; + + if(CurrentOutputFile==NULL) return; + + for(j=0;j")); + O(("#include ")); + O(("#include ")); + O(("#include ")); + O(("#include \"osiris_import.h\"")); + O(("#include \"osiris_common.h\"")); + O(("#include \"%s\"",DALLASFUNCS_FILENAME)); + O(("")); + + O(("#ifdef _MSC_VER //Visual C++ Build")); + O(("#define STDCALL __stdcall")); + O(("#define STDCALLPTR *STDCALL")); + O(("#else //Non-Visual C++ Build")); + O(("#define STDCALL __attribute__((stdcall))")); + O(("#define STDCALLPTR STDCALL*")); + O(("#endif")); + O(("")); + + O(("#ifdef __cplusplus")); + O(("extern \"C\"{")); + O(("#endif")); + O(("char STDCALL InitializeDLL(tOSIRISModuleInit *func_list);")); + O(("void STDCALL ShutdownDLL(void);")); + O(("int STDCALL GetGOScriptID(char *name,ubyte is_door);")); + O(("void STDCALLPTR CreateInstance(int id);")); + O(("void STDCALL DestroyInstance(int id,void *ptr);")); + O(("short STDCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data);")); + O(("int STDCALL GetTriggerScriptID(int trigger_room, int trigger_face );")); + O(("int STDCALL GetCOScriptList( int **list, int **id_list );")); + O(("int STDCALL SaveRestoreState( void *file_ptr, ubyte saving_state );")); + O(("#ifdef __cplusplus")); + O(("}")); + O(("#endif")); + O(("")); + + // Write out the script ID list + O(("// =================")); + O(("// Script ID Numbers")); + O(("// =================")); + + counter=0x000; + + // Write out the level ID + O(("#define %s 0x%03x",LEVEL_ID_NAME,counter++)); + O(("")); + + // Write out the custom object ID's (and count the number of custom object scripts) + num_CO_scripts=0; + for(j=0;jtype==SCRIPT_HEADER_NODE) { + O(("int %s = 0;",CreateScriptGlobalCtrName(data->ID))); + } + script_node=m_ScriptTree.GetNextSiblingItem(script_node); + } + O((" ")); + + O(("// ========================================")); + O(("// Function to Clear Global Action Counters")); + O(("// ========================================")); + O(("void ClearGlobalActionCtrs(void)")); + O(("{")); + + // Write out the clear script statements + script_node=m_ScriptTree.GetChildItem(TVI_ROOT); + while(script_node!=NULL) { + data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_node); + if(data!=NULL && data->type==SCRIPT_HEADER_NODE) { + O((" %s = 0;",CreateScriptGlobalCtrName(data->ID))); + } + script_node=m_ScriptTree.GetNextSiblingItem(script_node); + } + + O(("}")); + O((" ")); + + O(("// ========================================")); + O(("// Function to Save Global Action Counters")); + O(("// ========================================")); + O(("void SaveGlobalActionCtrs(void *file_ptr)")); + O(("{")); + + // Write out the clear script statements + script_node=m_ScriptTree.GetChildItem(TVI_ROOT); + while(script_node!=NULL) { + data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_node); + if(data!=NULL && data->type==SCRIPT_HEADER_NODE) { + O((" File_WriteInt(%s,file_ptr);",CreateScriptGlobalCtrName(data->ID))); + } + script_node=m_ScriptTree.GetNextSiblingItem(script_node); + } + + O(("}")); + O((" ")); + + O(("// ===========================================")); + O(("// Function to Restore Global Action Counters")); + O(("// ===========================================")); + O(("void RestoreGlobalActionCtrs(void *file_ptr)")); + O(("{")); + + // Write out the clear script statements + script_node=m_ScriptTree.GetChildItem(TVI_ROOT); + while(script_node!=NULL) { + data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_node); + if(data!=NULL && data->type==SCRIPT_HEADER_NODE) { + O((" %s=File_ReadInt(file_ptr);",CreateScriptGlobalCtrName(data->ID))); + } + script_node=m_ScriptTree.GetNextSiblingItem(script_node); + } + + O(("}")); + O((" ")); + + // Write out the Custom Script Block + WriteCustomScriptBlock(); + O((" ")); + + O(("// =================")); + O(("// Message File Data")); + O(("// =================")); + O((" ")); + O(("#define MAX_SCRIPT_MESSAGES 256")); + O(("#define MAX_MSG_FILEBUF_LEN 1024")); + O(("#define NO_MESSAGE_STRING \"*Message Not Found*\"")); + O(("#define INV_MSGNAME_STRING \"*Message Name Invalid*\"")); + O(("#define WHITESPACE_CHARS \" \\t\\r\\n\"")); + O((" ")); + O(("// Structure for storing a script message")); + O(("typedef struct {")); + O((" char *name; // the name of the message")); + O((" char *message; // the actual message text")); + O(("} tScriptMessage;")); + O((" ")); + O(("// Global storage for level script messages")); + O(("tScriptMessage *message_list[MAX_SCRIPT_MESSAGES];")); + O(("int num_messages;")); + O((" ")); + + O(("// ======================")); + O(("// Message File Functions")); + O(("// ======================")); + O((" ")); + O(("// Initializes the Message List")); + O(("void InitMessageList(void)")); + O(("{")); + O((" for(int j=0;jname);")); + O((" free(message_list[j]->message);")); + O((" free(message_list[j]);")); + O((" message_list[j]=NULL;")); + O((" }")); + O((" num_messages=0;")); + O(("}")); + O((" ")); + O(("// Adds a message to the list")); + O(("int AddMessageToList(char *name, char *msg)")); + O(("{")); + O((" int pos;")); + O((" ")); + O((" // Make sure there is room in the list")); + O((" if(num_messages>=MAX_SCRIPT_MESSAGES) return false;")); + O((" ")); + O((" // Allocate memory for this message entry")); + O((" pos=num_messages;")); + O((" message_list[pos]=(tScriptMessage *)malloc(sizeof(tScriptMessage));")); + O((" if(message_list[pos]==NULL) return false;")); + O((" ")); + O((" // Allocate memory for the message name")); + O((" message_list[pos]->name=(char *)malloc(strlen(name)+1);")); + O((" if(message_list[pos]->name==NULL) {")); + O((" free(message_list[pos]);")); + O((" return false;")); + O((" }")); + O((" strcpy(message_list[pos]->name,name);")); + O((" ")); + O((" // Allocate memory for the message name")); + O((" message_list[pos]->message=(char *)malloc(strlen(msg)+1);")); + O((" if(message_list[pos]->message==NULL) {")); + O((" free(message_list[pos]->name);")); + O((" free(message_list[pos]);")); + O((" return false;")); + O((" }")); + O((" strcpy(message_list[pos]->message,msg);")); + O((" num_messages++;")); + O((" ")); + O((" return true;")); + O(("}")); + O((" ")); + O(("// Removes any whitespace padding from the end of a string")); + O(("void RemoveTrailingWhitespace(char *s)")); + O(("{")); + O((" int last_char_pos;")); + O((" ")); + O((" last_char_pos=strlen(s)-1;")); + O((" while(last_char_pos>=0 && isspace(s[last_char_pos])) {")); + O((" s[last_char_pos]='\\0';")); + O((" last_char_pos--;")); + O((" }")); + O(("}")); + O((" ")); + O(("// Returns a pointer to the first non-whitespace char in given string")); + O(("char *SkipInitialWhitespace(char *s)")); + O(("{")); + O((" while((*s)!='\\0' && isspace(*s)) ")); + O((" s++;")); + O((" ")); + O((" return(s);")); + O(("}")); + O((" ")); + O(("// Read in the Messages")); + O(("int ReadMessageFile(char *filename)")); + O(("{")); + O((" void *infile;")); + O((" char filebuffer[MAX_MSG_FILEBUF_LEN+1];")); + O((" char *line, *msg_start;")); + O((" int line_num;")); + O((" bool next_msgid_found;")); + O((" ")); + O((" // Try to open the file for loading")); + O((" infile=File_Open(filename,\"rt\");")); + O((" if (!infile) return false;")); + O((" ")); + O((" line_num=0;")); + O((" next_msgid_found=true;")); + O((" ")); + O((" // Clear the message list")); + O((" ClearMessageList();")); + O((" ")); + O((" // Read in and parse each line of the file")); + O((" while (!File_eof(infile)) {")); + O((" ")); + O((" // Clear the buffer")); + O((" strcpy(filebuffer,\"\");")); + O((" ")); + O((" // Read in a line from the file")); + O((" File_ReadString(filebuffer, MAX_MSG_FILEBUF_LEN, infile);")); + O((" line_num++;")); + O((" ")); + O((" // Remove whitespace padding at start and end of line")); + O((" RemoveTrailingWhitespace(filebuffer);")); + O((" line=SkipInitialWhitespace(filebuffer);")); + O((" ")); + O((" // If line is a comment, or empty, discard it")); + O((" if(strlen(line)==0 || strncmp(line,\"//\",2)==0)")); + O((" continue;")); + O((" ")); + O((" if(!next_msgid_found) { // Parse out the last message ID number")); + O((" ")); + O((" // Grab the first keyword, make sure it's valid")); + O((" line=strtok(line,WHITESPACE_CHARS);")); + O((" if(line==NULL) continue;")); + O((" ")); + O((" // Grab the second keyword, and assign it as the next message ID")); + O((" line=strtok(NULL,WHITESPACE_CHARS);")); + O((" if(line==NULL) continue;")); + O((" ")); + O((" next_msgid_found=true;")); + O((" }")); + O((" else { // Parse line as a message line")); + O((" ")); + O((" // Find the start of message, and mark it")); + O((" msg_start=strchr(line,'=');")); + O((" if(msg_start==NULL) continue;")); + O((" msg_start[0]='\\0';")); + O((" msg_start++;")); + O((" ")); + O((" // Add the message to the list")); + O((" AddMessageToList(line,msg_start);")); + O((" }")); + O((" }")); + O((" File_Close(infile);")); + O((" ")); + O((" return true;")); + O(("}")); + O((" ")); + O(("// Find a message")); + O(("char *GetMessage(char *name)")); + O(("{")); + O((" // Make sure given name is valid")); + O((" if(name==NULL) return INV_MSGNAME_STRING;")); + O((" ")); + O((" // Search message list for name")); + O((" for(int j=0;jname,name)==0) return(message_list[j]->message);")); + O((" ")); + O((" // Couldn't find it")); + O((" return NO_MESSAGE_STRING;")); + O(("}")); + O((" ")); + + // Write out the global name arrays + WriteNameListArrays(); + + O(("// ===============")); + O(("// InitializeDLL()")); + O(("// ===============")); + O(("char STDCALL InitializeDLL(tOSIRISModuleInit *func_list)")); + O(("{")); + O((" osicommon_Initialize((tOSIRISModuleInit *)func_list);")); +#ifndef NEWEDITOR + O((" if(func_list->game_checksum!=CHECKSUM)")); + O((" { ")); + O((" mprintf(0,\"Game-Checksum FAIL!!! (%%ul!=%%ul)\\n\",func_list->game_checksum,CHECKSUM);")); + O((" mprintf(0,\"RECOMPILE YOUR SCRIPTS!!!\\n\");")); + O((" return 0;")); + O((" }")); +#endif + O((" ")); + O((" ClearGlobalActionCtrs();")); + O((" dfInit();")); + O((" InitMessageList();")); + O((" ")); + O((" // Build the filename of the message file")); + O((" char filename[_MAX_PATH+1];")); + O((" char english_filename[_MAX_PATH+1];")); + O((" int lang_type;")); + O((" if(func_list->script_identifier!=NULL) {")); + O((" _splitpath(func_list->script_identifier,NULL,NULL,filename,NULL);")); + O((" sprintf(english_filename,\"%%s.msg\",filename);")); + O((" lang_type=Game_GetLanguage();")); + O((" if(lang_type==LANGUAGE_FRENCH) strcat(filename,\"_FRN\");")); + O((" else if(lang_type==LANGUAGE_GERMAN) strcat(filename,\"_GER\");")); + O((" else if(lang_type==LANGUAGE_ITALIAN) strcat(filename,\"_ITN\");")); + O((" else if(lang_type==LANGUAGE_SPANISH) strcat(filename,\"_SPN\");")); + O((" else if(lang_type==LANGUAGE_POLISH) strcat(filename,\"_POL\");")); + O((" strcat(filename,\".msg\");")); + O((" }")); + O((" else {")); + O((" strcpy(filename,\"%s\");",m_ScriptMessagesFilename.GetBuffer(0))); + O((" lang_type=LANGUAGE_ENGLISH;")); + O((" }")); + O((" if(!ReadMessageFile(filename)) {")); + O((" if(lang_type == LANGUAGE_ENGLISH) {")); + O((" mprintf(0,\"ERROR: Could not load message file - %%s\\n\",filename);")); + O((" }")); + O((" else if(!ReadMessageFile(english_filename)) {")); + O((" mprintf(0,\"ERROR: Could not load message file - %%s\\n\",english_filename);")); + O((" }")); + O((" }")); + O((" ")); + + // Write out the name array lookup code + WriteNameArrayLookupCode(); + + O((" ")); + O((" return 1;")); + O(("}")); + O(("")); + + + + O(("// =============")); + O(("// ShutdownDLL()")); + O(("// =============")); + O(("void STDCALL ShutdownDLL(void)")); + O(("{")); + O((" ClearMessageList();")); + O(("}")); + O(("")); + + O(("// ===============")); + O(("// GetGOScriptID()")); + O(("// ===============")); + O(("int STDCALL GetGOScriptID(char *name,ubyte isdoor)")); + O(("{")); + O((" return -1;")); + O(("}")); + O(("")); + + O(("// ================")); + O(("// CreateInstance()")); + O(("// ================")); + O(("void STDCALLPTR CreateInstance(int id)")); + O(("{")); + O((" switch(id) {")); + + // Level Case + O((" case %s:",LEVEL_ID_NAME)); + O((" return new %s;",LEVEL_CLASS_NAME)); + O((" break;")); + + // Custom object Cases + for(j=0;jCallEvent(event,data);")); + O((" break;")); + + O((" default:")); + O((" mprintf(0,\"SCRIPT: Illegal ID (%%d)\\n\",id);")); + O((" break;")); + + O((" }")); + O((" return CONTINUE_CHAIN|CONTINUE_DEFAULT;")); + O(("}")); + O(("")); + + O(("// ==================")); + O(("// SaveRestoreState()")); + O(("// ==================")); + O(("int STDCALL SaveRestoreState( void *file_ptr, ubyte saving_state )")); + O(("{")); + O((" return 0;")); + O(("}")); + O(("")); + + O(("// ====================")); + O(("// GetTriggerScriptID()")); + O(("// ====================")); + O(("int STDCALL GetTriggerScriptID(int trigger_room,int trigger_face)")); + O(("{")); + + // Trigger ID Listing + for(j=0;j=0 && t=0) { + troom_text.Format("Trigger_rooms[%d]",index); + tface_text.Format("Trigger_faces[%d]",index); + } + } + + O((" if(trigger_room==%s && trigger_face==%s)",troom_text.GetBuffer(0),tface_text.GetBuffer(0))); + O((" return %s;",CreateScriptConstantName(j))); + O((" ")); + } + + O((" return -1;")); + O(("}")); + O(("")); + + O(("// =================")); + O(("// GetCOScriptList()")); + O(("// =================")); + O(("int STDCALL GetCOScriptList( int **list, int **id_list )")); + O(("{")); + + if(num_CO_scripts==0) { + O((" static int *cust_handle_list=NULL;")); + O((" static int *cust_id_list=NULL;")); + } + else { + O((" static int cust_handle_list[%d];",num_CO_scripts)); + O((" static int cust_id_list[%d] = { ",num_CO_scripts)); + + // Write out the custom object IDs + counter=0; + for(j=0;jtype!=OBJ_NONE && objp->name!=NULL) { + int index=FindObjectInList(objp->name); + if(index>=0 && strlen(objp->name)!=0) + handle_text.Format("Object_handles[%d]",index); + } + + if(counter==0) O((" // Fill in the custom handle list")); + O((" cust_handle_list[%d]=%s;",counter,handle_text.GetBuffer(0))); + counter++; + } + + O(("")); + O((" *list = cust_handle_list;")); + O((" *id_list = cust_id_list;")); + O(("")); + O((" return %d;",num_CO_scripts)); + O(("}")); + O(("")); + + O(("//=======================")); + O(("// Script Implementation ")); + O(("//=======================")); + O(("")); + + O(("BaseScript::BaseScript()")); + O(("{")); + O(("}")); + O(("")); + + O(("BaseScript::~BaseScript()")); + O(("{")); + O(("}")); + O(("")); + + O(("short BaseScript::CallEvent(int event,tOSIRISEventInfo *data)")); + O(("{")); + O((" mprintf(0,\"BaseScript::CallEvent()\\n\");")); + O((" return CONTINUE_CHAIN|CONTINUE_DEFAULT;")); + O(("}")); + O(("")); + + // Create the Level Script Class' CallEvent() method + O(("short %s::CallEvent(int event,tOSIRISEventInfo *data)",LEVEL_CLASS_NAME)); + O(("{")); + O((" switch(event) { ")); + + // Find the level script group (if it exists) + tScriptOwnerGroup *owner_group=NULL;; + for(j=0;jevt_savestate;")); + O((" ")); + O((" SaveGlobalActionCtrs(event_data->fileptr);")); + O((" dfSave(event_data->fileptr);")); + O(("#ifdef ENABLE_CUSTOM_SAVE_AND_RESTORE")); + O((" dsCustomSave(event_data->fileptr);")); + O(("#endif")); + O((" }")); + O((" break;")); + + // Handle the loading event + O((" case EVT_RESTORESTATE:")); + O((" {")); + O((" tOSIRISEVTRESTORESTATE *event_data=&data->evt_restorestate;")); + O((" ")); + O((" RestoreGlobalActionCtrs(event_data->fileptr);")); + O((" dfRestore(event_data->fileptr);")); + O(("#ifdef ENABLE_CUSTOM_SAVE_AND_RESTORE")); + O((" dsCustomRestore(event_data->fileptr);")); + O(("#endif")); + O((" }")); + O((" break;")); + + // Create the valid event case statements + for(j=0;jevent_sections[j]; + else + event_section=NULL; + + // See if this case has certain events + if(j!=LEVEL_START_EVENT_TYPE && (event_section==NULL || event_section->num_script_nodes==0)) continue; + + O((" case %s:",GetEventCodeName(j))); + O((" {")); + + // Get the event data code line and write it out + O((" %s",GetEventDataLine(j))); + + // If it's a LEVEL STARTED event, then initialize all the data + if(j==LEVEL_START_EVENT_TYPE) { + O((" ")); + O((" ClearGlobalActionCtrs();")); + O((" dfInit();")); + } + + // If it's a DESTROYED event, then add the conditional code to + // break out if the object is being destroyed because the level is ending + if(j==DESTROYED_EVENT_TYPE) { + O((" ")); + O((" // If destroy event is due to level ending, don't run scripts")); + O((" if(!event_data->is_dying) break;")); + } + + // If there is an owner group, do the scripts + if(event_section!=NULL) { + // Write out all the scripts for this event case + for(k=0;knum_script_nodes;k++) + WriteScriptCode(event_section->script_node_list[k]); + } + + O((" }")); + O((" break;")); + } +} + + +// Creates the event cases +void CDallasMainDlg::CreateEventCases(tScriptOwnerGroup *owner_group) +{ + int j,k; + + if(CurrentOutputFile==NULL || owner_group==NULL) return; + + // Create the valid event case statements + for(j=0;jevent_sections[j]; + if(event_section->num_script_nodes==0) continue; + O((" case %s:",GetEventCodeName(j))); + O((" {")); + + // Get the event data code line and write it out + O((" %s",GetEventDataLine(j))); + + // If it's a DESTROYED event, then add the conditional code to + // break out if the object is being destroyed because the level is ending + if(j==DESTROYED_EVENT_TYPE) { + O((" ")); + O((" // If destroy event is due to level ending, don't run scripts")); + O((" if(!event_data->is_dying) break;")); + } + + // Write out all the scripts for this event case + for(k=0;knum_script_nodes;k++) + WriteScriptCode(event_section->script_node_list[k]); + + O((" }")); + O((" break;")); + } +} + + +// Writes out the code for the given script (handles the top level IF-THEN) +void CDallasMainDlg::WriteScriptCode(HTREEITEM script_node) +{ + HTREEITEM conditional_header_node, action_header_node; + tTreeNodeData *data; + + if(CurrentOutputFile==NULL || script_node==NULL) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_node); + if(data==NULL || data->type!=SCRIPT_HEADER_NODE) return; + + // Comment this section of script + O((" ")); + O((" // Script %03d: %s",data->ID,data->name)); + + // Set the tab level + CurrentTabLevel=4; + + // Write out the top level conditional statement + conditional_header_node=GetConditionalHeaderNode(script_node); + WriteConditionalCodeBlock(conditional_header_node); + + // Write out the top level action block + action_header_node=GetActionHeaderNode(script_node); + WriteActionCodeBlock(action_header_node); +} + + +// Writes out the code body for a conditional header block (an IF statement) +void CDallasMainDlg::WriteConditionalCodeBlock(HTREEITEM conditional_header_node) +{ + tTreeNodeData *data, *action_hdr_data; + HTREEITEM child_node, action_hdr_node; + + if(CurrentOutputFile==NULL || conditional_header_node==NULL) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(conditional_header_node); + if(data==NULL || data->type!=CONDITIONAL_HEADER_NODE) return; + + // Get the first child (literal or query) + child_node=m_ScriptTree.GetChildItem(conditional_header_node); + if(child_node==NULL) return; + + TabOver(); + cfprintf(CurrentOutputFile,"if("); + + // Write out the max script execution times conditional (if it's not infinite) + action_hdr_data=NULL; + if(data->ID==TOP_LEVEL) { + action_hdr_node=GetActionHeaderNode(conditional_header_node); + if(action_hdr_node!=NULL) { + action_hdr_data=(tTreeNodeData *)m_ScriptTree.GetItemData(action_hdr_node); + if(action_hdr_data!=NULL && action_hdr_data->subID!=0) { + CString tmp_name=CreateScriptGlobalCtrName(GetScriptID(action_hdr_node)); + cfprintf(CurrentOutputFile,"(%s < %d) && (",tmp_name.GetBuffer(0),action_hdr_data->subID); + } + } + } + + // Write out the conditional expressions + WriteLogicalOpExpression(child_node); + + // If max script execution expression was added, then tack on another parentheses + if(action_hdr_data!=NULL && action_hdr_data->subID!=0) { + cfprintf(CurrentOutputFile,")"); + } + + O((")")); +} + + +// Writes out a logical operation block (AND, OR) +void CDallasMainDlg::WriteLogicalOpExpression(HTREEITEM logop_node) +{ + tTreeNodeData *data; + HTREEITEM child_node; + + if(CurrentOutputFile==NULL || logop_node==NULL) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(logop_node); + if(data==NULL || (data->type!=LOGICAL_OPERATOR_NODE && data->type!=CONDITIONAL_STATEMENT_NODE)) return; + + // If it's a Condition, write it out + if(data->type==CONDITIONAL_STATEMENT_NODE) { + WriteConditionalStatement(logop_node); + return; + } + + // If it's an AND or an OR, process it + if(data->ID==AND_TYPE || data->ID==OR_TYPE) { + child_node=m_ScriptTree.GetChildItem(logop_node); + while(child_node!=NULL) { + cfprintf(CurrentOutputFile,"("); + WriteLogicalOpExpression(child_node); + cfprintf(CurrentOutputFile,")"); + child_node=m_ScriptTree.GetNextSiblingItem(child_node); + if(child_node!=NULL) { + if(data->ID==AND_TYPE) + cfprintf(CurrentOutputFile," && "); + else + cfprintf(CurrentOutputFile," || "); + } + } + } +} + + +// Writes out a conditional statement +void CDallasMainDlg::WriteConditionalStatement(HTREEITEM condition_node) +{ + tTreeNodeData *data; + HTREEITEM child_node; + + if(CurrentOutputFile==NULL || condition_node==NULL) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(condition_node); + if(data==NULL || data->type!=CONDITIONAL_STATEMENT_NODE) return; + + // If it's an ALWAYS statement, just write out a 1 and get outta here + if(data->ID==ALWAYS_STATEMENT) { + cfprintf(CurrentOutputFile,"1"); + return; + } + + // Get the first child (literal or query) + child_node=m_ScriptTree.GetChildItem(condition_node); + if(child_node!=NULL) { + WriteFunctionParameter(child_node); + } + else { + cfprintf(CurrentOutputFile,"???"); + } + + // Get the second child (expression operator) + if(child_node!=NULL) { + child_node=m_ScriptTree.GetNextSiblingItem(child_node); + if(child_node!=NULL) { + tTreeNodeData *child_data; + child_data=(tTreeNodeData *)m_ScriptTree.GetItemData(child_node); + if(child_data!=NULL && child_data->type==EXPRESSION_OPERATOR_NODE) { + cfprintf(CurrentOutputFile,"%s",GetExpressionOperatorCodeName(child_data->subID)); + } + else + cfprintf(CurrentOutputFile,"/* Exp Op Error */"); + } + else { + cfprintf(CurrentOutputFile,"/* Exp Op Missing */"); + } + } + + // If it's a comparison, get the third child (literal or query) + if(child_node!=NULL && data->ID==COMPARISON_STATEMENT) { + child_node=m_ScriptTree.GetNextSiblingItem(child_node); + if(child_node!=NULL) { + WriteFunctionParameter(child_node); + } + else { + cfprintf(CurrentOutputFile,"/* 2nd Comparison Value Missing */"); + } + } +} + + +// Writes out a query function call +void CDallasMainDlg::WriteQueryFunctionCall(HTREEITEM query_node) +{ + tTreeNodeData *data; + + if(CurrentOutputFile==NULL || query_node==NULL) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(query_node); + if(data==NULL || data->type!=EXPRESSION_NODE) return; + + // Check Query ID validity + if(data->ID<0 || data->ID>=m_NumQueries) { + cfprintf(CurrentOutputFile,"/* ERROR: Invalid Query Function Encountered!!! */"); + return; + } + + // Handle the DALLAS custom queries first + if(strcmp(m_QueryDatabase[data->ID].func,"qScriptExecuted_DALLAS")==0) { + HTREEITEM child_node; + tTreeNodeData *child_data; + child_node=m_ScriptTree.GetChildItem(query_node); + if(child_node==NULL) return; + child_data=(tTreeNodeData *)m_ScriptTree.GetItemData(child_node); + if(child_data==NULL || child_data->type!=PARAMETER_NODE || child_data->ID!=SCRIPT_PARAMETER_TYPE) return; + CString tmp_name=CreateScriptGlobalCtrName(child_data->int_val); + cfprintf(CurrentOutputFile,"(%s > 0)",tmp_name.GetBuffer(0)); + return; + } + if(strcmp(m_QueryDatabase[data->ID].func,"qTimesScriptExecuted_DALLAS")==0) { + HTREEITEM child_node; + tTreeNodeData *child_data; + child_node=m_ScriptTree.GetChildItem(query_node); + if(child_node==NULL) return; + child_data=(tTreeNodeData *)m_ScriptTree.GetItemData(child_node); + if(child_data==NULL || child_data->type!=PARAMETER_NODE || child_data->ID!=SCRIPT_PARAMETER_TYPE) return; + CString tmp_name=CreateScriptGlobalCtrName(child_data->int_val); + cfprintf(CurrentOutputFile,"%s",tmp_name.GetBuffer(0)); + return; + } + + // Write out the function name + cfprintf(CurrentOutputFile,"%s(",m_QueryDatabase[data->ID].func); + + // Write out the parameter arguments + HTREEITEM param_node; + + param_node=m_ScriptTree.GetChildItem(query_node); + while(param_node!=NULL) { + WriteFunctionParameter(param_node); + param_node=m_ScriptTree.GetNextSiblingItem(param_node); + if(param_node!=NULL) cfprintf(CurrentOutputFile,", "); + } + cfprintf(CurrentOutputFile,")"); +} + + +// Writes out the code body for an action header block (the block to immediately follow an IF statement) +void CDallasMainDlg::WriteActionCodeBlock(HTREEITEM action_header_node) +{ + HTREEITEM child_node; + tTreeNodeData *header_data, *data; + + if(action_header_node==NULL) return; + + header_data=(tTreeNodeData *)m_ScriptTree.GetItemData(action_header_node); + if(header_data==NULL || header_data->type!=ACTIONS_HEADER_NODE) return; + + // Write out starting brace + TabOver(); + if(header_data->ID==NESTED && header_data->subID==ELSE_CLAUSE) + O(("else {")); + else + O(("{")); + + CurrentTabLevel++; + + child_node=m_ScriptTree.GetChildItem(action_header_node); + while(child_node!=NULL) { + + // Get the type of child node this is + data=(tTreeNodeData *)m_ScriptTree.GetItemData(child_node); + if(data != NULL) { + if(data->type==ACTION_STATEMENT_NODE) { + WriteActionFunctionCall(child_node); + } + else if(data->type==CONDITIONAL_HEADER_NODE) { + WriteConditionalCodeBlock(child_node); + } + else if(data->type==ACTIONS_HEADER_NODE) { + WriteActionCodeBlock(child_node); + } + } + + // Get the next node + child_node=m_ScriptTree.GetNextSiblingItem(child_node); + } + + // If it's a top level action header node, increment the global counter + if(header_data->ID==TOP_LEVEL) { + CString tmp_name=CreateScriptGlobalCtrName(GetScriptID(action_header_node)); + + TabOver(); O(("")); + TabOver(); O(("// Increment the script action counter")); + TabOver(); O(("if(%s < MAX_ACTION_CTR_VALUE) %s++;",tmp_name.GetBuffer(0),tmp_name.GetBuffer(0))); + + // If user wants to break script chain, do it here + if(header_data->int_val==BREAK_SCRIPT_CHAIN) { + TabOver(); O(("")); + TabOver(); O(("return CONTINUE_DEFAULT;")); + } + } + + CurrentTabLevel--; + + // Write out closing brace + TabOver(); + O(("}")); +} + + +// Writes out an action function call +void CDallasMainDlg::WriteActionFunctionCall(HTREEITEM action_node) +{ + tTreeNodeData *data; + + if(CurrentOutputFile==NULL || action_node==NULL) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(action_node); + if(data==NULL || data->type!=ACTION_STATEMENT_NODE) return; + + // Check Action ID validity + if(data->ID<0 || data->ID>=m_NumActions) { + if(data->ID != DO_NOTHING_ID) { + TabOver(); + O(("// ERROR: Invalid Action Function Encountered!!!")); + } + return; + } + + // Write out the function name + TabOver(); + cfprintf(CurrentOutputFile,"%s(",m_ActionDatabase[data->ID].func); + + // Write out the parameter arguments + HTREEITEM param_node; + + param_node=m_ScriptTree.GetChildItem(action_node); + while(param_node!=NULL) { + WriteFunctionParameter(param_node); + param_node=m_ScriptTree.GetNextSiblingItem(param_node); + if(param_node!=NULL) cfprintf(CurrentOutputFile,", "); + } + O((");")); +} + + +// Writes out an action function call +void CDallasMainDlg::WriteFunctionParameter(HTREEITEM param_node) +{ + tTreeNodeData *data; + int index; + + if(CurrentOutputFile==NULL || param_node==NULL) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(param_node); + if(data==NULL || (data->type!=PARAMETER_NODE && data->type!=EXPRESSION_NODE)) return; + + // If it's a query, write out the query function + if(data->type==EXPRESSION_NODE) { + WriteQueryFunctionCall(param_node); + return; + } + + // Output the parameter values + switch(data->ID) { + case DOOR_PARAMETER_TYPE: + if(data->subID == USE_IT_HANDLE) + cfprintf(CurrentOutputFile,"event_data->it_handle"); + else if(data->subID == USE_ME_HANDLE) + cfprintf(CurrentOutputFile,"data->me_handle"); + else { + int index=FindDoorInList(data->str_val); + if(index<0 || strlen(data->str_val)==0) + cfprintf(CurrentOutputFile,"%d",OBJECT_HANDLE_NONE); + else + cfprintf(CurrentOutputFile,"Door_handles[%d]",index); + } + break; + case OBJECT_PARAMETER_TYPE: + if(data->subID == USE_IT_HANDLE) + cfprintf(CurrentOutputFile,"event_data->it_handle"); + else if(data->subID == USE_ME_HANDLE) + cfprintf(CurrentOutputFile,"data->me_handle"); + else { + int index=FindObjectInList(data->str_val); + if(index<0 || strlen(data->str_val)==0) + cfprintf(CurrentOutputFile,"%d",OBJECT_HANDLE_NONE); + else + cfprintf(CurrentOutputFile,"Object_handles[%d]",index); + } + break; + case ROOM_PARAMETER_TYPE: + index=FindRoomInList(data->str_val); + if(index<0 || strlen(data->str_val)==0) + cfprintf(CurrentOutputFile,"%d",-1); + else + cfprintf(CurrentOutputFile,"Room_indexes[%d]",index); + break; + case TRIGGER_PARAMETER_TYPE: + index=FindTriggerInList(data->str_val); + if(index<0 || strlen(data->str_val)==0) + cfprintf(CurrentOutputFile,"%d",-1); + else + cfprintf(CurrentOutputFile,"Trigger_indexes[%d]",index); + break; + case INT_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%d",data->int_val); + break; + case BOOL_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%d",data->int_val); + break; + case FLOAT_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%ff",data->float_val1); + break; + case VECTOR_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"NO VECTOR YET"); + break; + case STRING_PARAMETER_TYPE: + index=FindMessageNameInList(data->str_val); + if(index<0 || strlen(data->str_val)==0) + cfprintf(CurrentOutputFile,"\"*MESSAGE_ERROR*\""); + else + cfprintf(CurrentOutputFile,"Message_strings[%d]",index); + break; + case PERCENTAGE_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%ff",data->float_val1); + break; + case ENUM_PARAMETER_TYPE: + if(data->subID == USE_GOALID_VALUE) + cfprintf(CurrentOutputFile,"event_data->goal_uid"); + else if(data->subID == USE_TIMERID_VALUE) + cfprintf(CurrentOutputFile,"event_data->id"); + else if(data->subID == USE_MATCENID_VALUE) + cfprintf(CurrentOutputFile,"event_data->id"); + else { + cfprintf(CurrentOutputFile,"%d",data->int_val); + } + break; + case SCRIPT_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%d",data->int_val); + break; + case SOUND_PARAMETER_TYPE: + index=FindSoundInList(data->str_val); + if(index<0 || strlen(data->str_val)==0) + cfprintf(CurrentOutputFile,"%d",-1); + else + cfprintf(CurrentOutputFile,"Sound_indexes[%d]",index); + break; + case SPECNAME_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"\"%s\"",data->str_val); + break; + case TEXTURE_PARAMETER_TYPE: + index=FindTextureInList(data->str_val); + if(index<0 || strlen(data->str_val)==0) + cfprintf(CurrentOutputFile,"%d",-1); + else + cfprintf(CurrentOutputFile,"Texture_indexes[%d]",index); + break; + case FLAG_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%d",data->int_val); + break; + case PATH_PARAMETER_TYPE: + index=FindPathInList(data->str_val); + if(index<0 || strlen(data->str_val)==0) + cfprintf(CurrentOutputFile,"%d",-1); + else + cfprintf(CurrentOutputFile,"Path_indexes[%d]",index); + break; + case MATCEN_PARAMETER_TYPE: + if(data->subID == USE_MATCEN_EVENT_ID) { + cfprintf(CurrentOutputFile,"event_data->id"); + } + else { + index=FindMatcenInList(data->str_val); + if(index<0 || strlen(data->str_val)==0) + cfprintf(CurrentOutputFile,"%d",-1); + else + cfprintf(CurrentOutputFile,"Matcen_indexes[%d]",index); + } + break; + case LEVEL_GOAL_PARAMETER_TYPE: + if(data->subID == USE_LEVEL_GOAL_ID) { + cfprintf(CurrentOutputFile,"event_data->level_goal_index"); + } + else { + index=FindGoalInList(data->str_val); + if(index<0 || strlen(data->str_val)==0) + cfprintf(CurrentOutputFile,"%d",-1); + else + cfprintf(CurrentOutputFile,"Goal_indexes[%d]",index); + } + break; + case STRM_AUDIO_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"\"%s\"",data->str_val); + break; + default: + break; + } +} + + +// Creates the tree block (for saving scripts) +void CDallasMainDlg::WriteScriptSaveBlock(void) +{ + if(CurrentOutputFile==NULL) return; + + // Create the header + O((" ")); + O((" ")); + O(("/*********************************************************")); + O(("Script Save Block: DO NOT TOUCH ANYTHING IN THIS BLOCK!!! ")); + O(("**********************************************************")); + O(("%s",SCRIPT_BLOCK_START_TAG)); + O((" ")); + O(("VERSION %d",DALLAS_SAVE_VERSION)); + O(("NEXT_ID %d",m_NextScriptID)); + O((" ")); + O(("// UserType value blocks")); + + // Writes out the name lists + WriteUserTypeVals(); + + O((" ")); + O(("// Name Lists")); + // Writes out the name lists + WriteNameLists(); + + O((" ")); + O(("// Script Tree Dump")); + + // Write out the list of nodes + WriteScriptTreeDump(); + + O((" ")); + O(("%s",SCRIPT_BLOCK_END_TAG)); + O(("*********************************************************/")); +} + + +// Writes out the UserType value blocks +void CDallasMainDlg::WriteUserTypeVals(void) +{ + int j,k; + + if(CurrentOutputFile==NULL) return; + + for(j=0;jvalue!=-1) + O(("%d:%s",value_entry->value,value_entry->name)); + } + O(("%s",USERTYPE_VALS_END_TAG)); + O((" ")); + } + } +} + + +// Writes out the name lists +void CDallasMainDlg::WriteNameLists(void) +{ + int j; + + if(CurrentOutputFile==NULL) return; + + // Write out the door list + O(("%s",DOOR_LIST_START_TAG)); + for(j=0;j0) { + O(("char *Door_names[NUM_DOOR_NAMES] = {")); + for(j=0;j<(m_DoorListSize-1);j++) + O((" \"%s\",",m_DoorList[j])); + O((" \"%s\"",m_DoorList[j])); + O(("};")); + O(("int Door_handles[NUM_DOOR_NAMES];")); + } + else { + O(("char **Door_names=NULL;")); + O(("int *Door_handles=NULL;")); + } + O((" ")); + + // Write out the object list + O(("#define NUM_OBJECT_NAMES %d",m_ObjectListSize)); + if(m_ObjectListSize>0) { + O(("char *Object_names[NUM_OBJECT_NAMES] = {")); + for(j=0;j<(m_ObjectListSize-1);j++) + O((" \"%s\",",m_ObjectList[j])); + O((" \"%s\"",m_ObjectList[j])); + O(("};")); + O(("int Object_handles[NUM_OBJECT_NAMES];")); + } + else { + O(("char **Object_names=NULL;")); + O(("int *Object_handles=NULL;")); + } + O((" ")); + + // Write out the room list + O(("#define NUM_ROOM_NAMES %d",m_RoomListSize)); + if(m_RoomListSize>0) { + O(("char *Room_names[NUM_ROOM_NAMES] = {")); + for(j=0;j<(m_RoomListSize-1);j++) + O((" \"%s\",",m_RoomList[j])); + O((" \"%s\"",m_RoomList[j])); + O(("};")); + O(("int Room_indexes[NUM_ROOM_NAMES];")); + } + else { + O(("char **Room_names=NULL;")); + O(("int *Room_indexes=NULL;")); + } + O((" ")); + + // Write out the Trigger list + O(("#define NUM_TRIGGER_NAMES %d",m_TriggerListSize)); + if(m_TriggerListSize>0) { + O(("char *Trigger_names[NUM_TRIGGER_NAMES] = {")); + for(j=0;j<(m_TriggerListSize-1);j++) + O((" \"%s\",",m_TriggerList[j])); + O((" \"%s\"",m_TriggerList[j])); + O(("};")); + O(("int Trigger_indexes[NUM_TRIGGER_NAMES];")); + O(("int Trigger_faces[NUM_TRIGGER_NAMES];")); + O(("int Trigger_rooms[NUM_TRIGGER_NAMES];")); + } + else { + O(("char **Trigger_names=NULL;")); + O(("int *Trigger_indexes=NULL;")); + O(("int *Trigger_faces=NULL;")); + O(("int *Trigger_rooms=NULL;")); + } + O((" ")); + + // Write out the sound list + O(("#define NUM_SOUND_NAMES %d",m_SoundListSize)); + if(m_SoundListSize>0) { + O(("char *Sound_names[NUM_SOUND_NAMES] = {")); + for(j=0;j<(m_SoundListSize-1);j++) + O((" \"%s\",",m_SoundList[j])); + O((" \"%s\"",m_SoundList[j])); + O(("};")); + O(("int Sound_indexes[NUM_SOUND_NAMES];")); + } + else { + O(("char **Sound_names=NULL;")); + O(("int *Sound_indexes=NULL;")); + } + O((" ")); + + // Write out the texture list + O(("#define NUM_TEXTURE_NAMES %d",m_TextureListSize)); + if(m_TextureListSize>0) { + O(("char *Texture_names[NUM_TEXTURE_NAMES] = {")); + for(j=0;j<(m_TextureListSize-1);j++) + O((" \"%s\",",m_TextureList[j])); + O((" \"%s\"",m_TextureList[j])); + O(("};")); + O(("int Texture_indexes[NUM_TEXTURE_NAMES];")); + } + else { + O(("char **Texture_names=NULL;")); + O(("int *Texture_indexes=NULL;")); + } + O((" ")); + + // Write out the Path list + O(("#define NUM_PATH_NAMES %d",m_PathListSize)); + if(m_PathListSize>0) { + O(("char *Path_names[NUM_PATH_NAMES] = {")); + for(j=0;j<(m_PathListSize-1);j++) + O((" \"%s\",",m_PathList[j])); + O((" \"%s\"",m_PathList[j])); + O(("};")); + O(("int Path_indexes[NUM_PATH_NAMES];")); + } + else { + O(("char **Path_names=NULL;")); + O(("int *Path_indexes=NULL;")); + } + O((" ")); + + // Write out the Matcen list + O(("#define NUM_MATCEN_NAMES %d",m_MatcenListSize)); + if(m_MatcenListSize>0) { + O(("char *Matcen_names[NUM_MATCEN_NAMES] = {")); + for(j=0;j<(m_MatcenListSize-1);j++) + O((" \"%s\",",m_MatcenList[j])); + O((" \"%s\"",m_MatcenList[j])); + O(("};")); + O(("int Matcen_indexes[NUM_MATCEN_NAMES];")); + } + else { + O(("char **Matcen_names=NULL;")); + O(("int *Matcen_indexes=NULL;")); + } + O((" ")); + + // Write out the Goal list + O(("#define NUM_GOAL_NAMES %d",m_GoalListSize)); + if(m_GoalListSize>0) { + O(("char *Goal_names[NUM_GOAL_NAMES] = {")); + for(j=0;j<(m_GoalListSize-1);j++) + O((" \"%s\",",m_GoalList[j])); + O((" \"%s\"",m_GoalList[j])); + O(("};")); + O(("int Goal_indexes[NUM_GOAL_NAMES];")); + } + else { + O(("char **Goal_names=NULL;")); + O(("int *Goal_indexes=NULL;")); + } + O((" ")); + + // Write out the message name list + O(("#define NUM_MESSAGE_NAMES %d",m_MessageNameListSize)); + if(m_MessageNameListSize>0) { + O(("char *Message_names[NUM_MESSAGE_NAMES] = {")); + for(j=0;j<(m_MessageNameListSize-1);j++) + O((" \"%s\",",m_MessageNameList[j])); + O((" \"%s\"",m_MessageNameList[j])); + O(("};")); + O(("char *Message_strings[NUM_MESSAGE_NAMES];")); + } + else { + O(("char **Message_names=NULL;")); + O(("char **Message_strings=NULL;")); + } + O((" ")); +} + + +// Writes out the name list lookup code +void CDallasMainDlg::WriteNameArrayLookupCode(void) +{ + O((" int j;")); + O((" ")); + O((" // Do Door Index lookups")); + O((" for(j=0;jtype==SCRIPT_HEADER_NODE) { + if(DALLAS_SAVE_VERSION>=1) + WriteScriptNodeDump_v1U(node); + else + WriteScriptNodeDump_v0(node); + + WriteScriptChildrenDump(node); + } + + node=m_ScriptTree.GetNextSiblingItem(node); + } +} + + +// Writes out codes versions of all children of the given node +void CDallasMainDlg::WriteScriptChildrenDump(HTREEITEM parent, bool filter_on/*=FALSE*/) +{ + HTREEITEM child_node; + + if(CurrentOutputFile==NULL || parent==NULL) return; + + // Make sure the parent has at least one child + child_node=m_ScriptTree.GetChildItem(parent); + if(child_node==NULL) return; + + // Write out each child node (and any of their children) + CurrentTabLevel++; + TabOver(); O(("%s",CHILD_BLOCK_START_TAG)); + while(child_node!=NULL) { + + if(DALLAS_SAVE_VERSION>=1) + WriteScriptNodeDump_v1U(child_node,filter_on); + else + WriteScriptNodeDump_v0(child_node); + + WriteScriptChildrenDump(child_node,filter_on); + child_node=m_ScriptTree.GetNextSiblingItem(child_node); + } + TabOver(); O(("%s",CHILD_BLOCK_END_TAG)); + CurrentTabLevel--; +} + + +// VERSION 0: Writes out a coded version of the given script node +void CDallasMainDlg::WriteScriptNodeDump_v0(HTREEITEM node) +{ + tTreeNodeData *data; + CString tmp_name; + int index; + char goal_name[MAX_PATH+1]; + + if(CurrentOutputFile==NULL || node==NULL) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); + if(data==NULL) return; + + TabOver(); + switch(data->type) { + case SCRIPT_HEADER_NODE: + cfprintf(CurrentOutputFile,"%02d:%d:%s", + data->type, + data->ID, + data->name); + break; + case SCRIPT_OWNER_NODE: + cfprintf(CurrentOutputFile,"%02d:%d:%d", + data->type, + data->ID, + data->int_val); + break; + case SCRIPT_EVENT_NODE: + cfprintf(CurrentOutputFile,"%02d:%d", + data->type, + data->ID); + break; + case CONDITIONAL_HEADER_NODE: + cfprintf(CurrentOutputFile,"%02d:%d", + data->type, + data->ID); + break; + case ACTIONS_HEADER_NODE: + cfprintf(CurrentOutputFile,"%02d:%d:%d", + data->type, + data->ID, + data->subID); + break; + case CONDITIONAL_STATEMENT_NODE: + cfprintf(CurrentOutputFile,"%02d:%d", + data->type, + data->ID); + break; + case EXPRESSION_NODE: + cfprintf(CurrentOutputFile,"%02d:%s:%s", + data->type, + GetQueryFunc(data->ID), + data->name); + break; + case EXPRESSION_OPERATOR_NODE: + cfprintf(CurrentOutputFile,"%02d:%d:%d", + data->type, + data->ID, + data->subID); + break; + case ACTION_STATEMENT_NODE: + cfprintf(CurrentOutputFile,"%02d:%s", + data->type, + GetActionFunc(data->ID)); + break; + case LOGICAL_OPERATOR_NODE: + cfprintf(CurrentOutputFile,"%02d:%d", + data->type, + data->ID); + break; + case PARAMETER_NODE: + // Get image type based upon what kind of parameter it is + switch(data->ID) { + case DOOR_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", + data->type, + data->ID, + data->subID, + data->int_val, + data->name); + break; + case OBJECT_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", + data->type, + data->ID, + data->subID, + data->int_val, + data->name); + break; + case ROOM_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + data->int_val, + data->name); + break; + case TRIGGER_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + data->int_val, + data->name); + break; + case INT_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + data->int_val, + data->name); + break; + case BOOL_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + data->int_val, + data->name); + break; + case FLOAT_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%f:%s", + data->type, + data->ID, + data->float_val1, + data->name); + break; + case VECTOR_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%f:%f:%f:%s", + data->type, + data->ID, + data->float_val1, + data->float_val2, + data->float_val3, + data->name); + break; + case STRING_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%s:%s", + data->type, + data->ID, + data->str_val, + data->name); + break; + case PERCENTAGE_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%f:%s", + data->type, + data->ID, + data->float_val1, + data->name); + break; + case ENUM_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + data->int_val, + data->name); + break; + case SCRIPT_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + data->int_val, + data->name); + break; + case SOUND_PARAMETER_TYPE: + if(data->int_val==NOT_SPECIFIED_TYPE) + index=-1; + else + index=FindSoundInList(Sounds[data->int_val].name); + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + index, + data->name); + break; + case SPECNAME_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%s:%s", + data->type, + data->ID, + data->str_val, + data->name); + break; + case TEXTURE_PARAMETER_TYPE: + if(data->int_val==NOT_SPECIFIED_TYPE) + index=-1; + else + index=FindTextureInList(GameTextures[data->int_val].name); + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + index, + data->name); + break; + case FLAG_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + data->int_val, + data->name); + break; + case PATH_PARAMETER_TYPE: + if(data->int_val==NOT_SPECIFIED_TYPE) + index=-1; + else + index=FindPathInList(GamePaths[data->int_val].name); + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + index, + data->name); + break; + case MATCEN_PARAMETER_TYPE: + if(data->subID==USE_MATCEN_VALUE) { + if(data->int_val==NOT_SPECIFIED_TYPE || !MatcenValid(data->int_val)) + index=-1; + else { + char matcen_name[MAX_MATCEN_NAME_LEN+1]; + Matcen[data->int_val]->GetName(matcen_name); + index=FindMatcenInList(matcen_name); + } + } + else + index=data->int_val; + cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", + data->type, + data->ID, + data->subID, + index, + data->name); + break; + case LEVEL_GOAL_PARAMETER_TYPE: + if(data->subID==USE_LEVEL_GOAL_VALUE) { + if(data->int_val==NOT_SPECIFIED_TYPE || Level_goals.GoalGetName(data->int_val,goal_name,MAX_PATH)<0) + index=-1; + else { + index=FindGoalInList(goal_name); + } + } + else + index=data->int_val; + cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", + data->type, + data->ID, + data->subID, + index, + data->name); + break; + case STRM_AUDIO_PARAMETER_TYPE: + if(strlen(data->str_val)==0) + index=NOT_SPECIFIED_TYPE; + else + index=FindStrmAudioInList(data->str_val); + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + index, + data->name); + break; + default: + cfprintf(CurrentOutputFile,"%02d:%d:%s", + data->type, + data->ID, + data->name); + break; + } + break; + case PARAMETER_OPERATOR_NODE: + cfprintf(CurrentOutputFile,"%02d:%d", + data->type, + data->ID); + break; + case UNKNOWN_NODE: + cfprintf(CurrentOutputFile,"%02d:%d", + data->type, + data->ID); + break; + default: + cfprintf(CurrentOutputFile,"%02d:%d", + UNKNOWN_NODE, + data->ID); + break; + } + O((" ")); +} + + +// VERSION 1: Writes out a coded version of the given script node +void CDallasMainDlg::WriteScriptNodeDump_v1U(HTREEITEM node, bool filter_on/*=FALSE*/) +{ + tTreeNodeData *data; + CString tmp_name; + int index; + + if(CurrentOutputFile==NULL || node==NULL) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); + if(data==NULL) return; + + TabOver(); + switch(data->type) { + case SCRIPT_HEADER_NODE: + cfprintf(CurrentOutputFile,"%02d:%d:%s", + data->type, + data->ID, + data->name); + break; + case SCRIPT_OWNER_NODE: + if(data->ID==OBJECT_TYPE) { + if(filter_on || data->int_val==OBJECT_HANDLE_NONE || strlen(data->str_val)==0) + index=OBJECT_NONE_HANDLE; + else + index=FindObjectInList(data->str_val); + } + else if(data->ID==TRIGGER_TYPE) { + if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) + index=NOT_SPECIFIED_TYPE; + else + index=FindTriggerInList(data->str_val); + } + else + index=data->int_val; + cfprintf(CurrentOutputFile,"%02d:%d:%d", + data->type, + data->ID, + index); + break; + case SCRIPT_EVENT_NODE: + cfprintf(CurrentOutputFile,"%02d:%d", + data->type, + data->ID); + break; + case CONDITIONAL_HEADER_NODE: + cfprintf(CurrentOutputFile,"%02d:%d", + data->type, + data->ID); + break; + case ACTIONS_HEADER_NODE: + if(DALLAS_SAVE_VERSION>=3) { + cfprintf(CurrentOutputFile,"%02d:%d:%d:%d", + data->type, + data->ID, + data->int_val, + data->subID); + } + else { + cfprintf(CurrentOutputFile,"%02d:%d:%d", + data->type, + data->ID, + data->subID); + } + break; + case CONDITIONAL_STATEMENT_NODE: + cfprintf(CurrentOutputFile,"%02d:%d", + data->type, + data->ID); + break; + case EXPRESSION_NODE: + cfprintf(CurrentOutputFile,"%02d:%s:%s", + data->type, + GetQueryFunc(data->ID), + data->name); + break; + case EXPRESSION_OPERATOR_NODE: + cfprintf(CurrentOutputFile,"%02d:%d:%d", + data->type, + data->ID, + data->subID); + break; + case ACTION_STATEMENT_NODE: + cfprintf(CurrentOutputFile,"%02d:%s", + data->type, + GetActionFunc(data->ID)); + break; + case LOGICAL_OPERATOR_NODE: + cfprintf(CurrentOutputFile,"%02d:%d", + data->type, + data->ID); + break; + case PARAMETER_NODE: + // Get image type based upon what kind of parameter it is + switch(data->ID) { + case DOOR_PARAMETER_TYPE: + if(data->subID==USE_OBJECT_HANDLE) { + if(filter_on || data->int_val==OBJECT_HANDLE_NONE || strlen(data->str_val)==0) + index=OBJECT_NONE_HANDLE; + else + index=FindDoorInList(data->str_val); + } + else + index=data->int_val; + cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", + data->type, + data->ID, + data->subID, + index, + data->name); + break; + case OBJECT_PARAMETER_TYPE: + if(data->subID==USE_OBJECT_HANDLE) { + if(filter_on || data->int_val==OBJECT_HANDLE_NONE || strlen(data->str_val)==0) + index=OBJECT_NONE_HANDLE; + else + index=FindObjectInList(data->str_val); + } + else + index=data->int_val; + cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", + data->type, + data->ID, + data->subID, + index, + data->name); + break; + case ROOM_PARAMETER_TYPE: + if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) + index=NOT_SPECIFIED_TYPE; + else + index=FindRoomInList(data->str_val); + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + index, + data->name); + break; + case TRIGGER_PARAMETER_TYPE: + if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) + index=NOT_SPECIFIED_TYPE; + else + index=FindTriggerInList(data->str_val); + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + index, + data->name); + break; + case INT_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + data->int_val, + data->name); + break; + case BOOL_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + data->int_val, + data->name); + break; + case FLOAT_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%f:%s", + data->type, + data->ID, + data->float_val1, + data->name); + break; + case VECTOR_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%f:%f:%f:%s", + data->type, + data->ID, + data->float_val1, + data->float_val2, + data->float_val3, + data->name); + break; + case STRING_PARAMETER_TYPE: + if(filter_on || strlen(data->str_val)==0) + tmp_name=NOT_SPECIFIED_MSG; + else + tmp_name=data->str_val; + cfprintf(CurrentOutputFile,"%02d:%d:%s:%s", + data->type, + data->ID, + tmp_name.GetBuffer(0), + data->name); + break; + case PERCENTAGE_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%f:%s", + data->type, + data->ID, + data->float_val1, + data->name); + break; + case ENUM_PARAMETER_TYPE: + if(DALLAS_SAVE_VERSION>=2) { + cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", + data->type, + data->ID, + data->subID, + data->int_val, + data->name); + } + else { + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + data->int_val, + data->name); + } + break; + case SCRIPT_PARAMETER_TYPE: + if(filter_on) + index=NOT_SPECIFIED_TYPE; + else + index=data->int_val; + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + index, + data->name); + break; + case SOUND_PARAMETER_TYPE: + if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) + index=NOT_SPECIFIED_TYPE; + else + index=FindSoundInList(data->str_val); + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + index, + data->name); + break; + case SPECNAME_PARAMETER_TYPE: + if(filter_on || strlen(data->str_val)==0) + index=NOT_SPECIFIED_TYPE; + else + index=FindSpecnameInList(data->str_val); + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + index, + data->name); + break; + case TEXTURE_PARAMETER_TYPE: + if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) + index=NOT_SPECIFIED_TYPE; + else + index=FindTextureInList(data->str_val); + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + index, + data->name); + break; + case FLAG_PARAMETER_TYPE: + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + data->int_val, + data->name); + break; + case PATH_PARAMETER_TYPE: + if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) + index=NOT_SPECIFIED_TYPE; + else + index=FindPathInList(data->str_val); + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + index, + data->name); + break; + case MATCEN_PARAMETER_TYPE: + if(data->subID==USE_MATCEN_VALUE) { + if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) + index=NOT_SPECIFIED_TYPE; + else + index=FindMatcenInList(data->str_val); + } + else + index=data->int_val; + cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", + data->type, + data->ID, + data->subID, + index, + data->name); + break; + case LEVEL_GOAL_PARAMETER_TYPE: + if(data->subID==USE_LEVEL_GOAL_VALUE) { + if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) + index=NOT_SPECIFIED_TYPE; + else { + index=FindGoalInList(data->str_val); + } + } + else + index=data->int_val; + cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", + data->type, + data->ID, + data->subID, + index, + data->name); + break; + case STRM_AUDIO_PARAMETER_TYPE: + if(filter_on || strlen(data->str_val)==0) + index=NOT_SPECIFIED_TYPE; + else + index=FindStrmAudioInList(data->str_val); + cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", + data->type, + data->ID, + index, + data->name); + break; + default: + cfprintf(CurrentOutputFile,"%02d:%d:%s", + data->type, + data->ID, + data->name); + break; + } + break; + case PARAMETER_OPERATOR_NODE: + cfprintf(CurrentOutputFile,"%02d:%d", + data->type, + data->ID); + break; + case UNKNOWN_NODE: + cfprintf(CurrentOutputFile,"%02d:%d", + data->type, + data->ID); + break; + default: + cfprintf(CurrentOutputFile,"%02d:%d", + UNKNOWN_NODE, + data->ID); + break; + } + O((" ")); +} + + +///////////////////////////////////////////////////////////////////////////// +// Object Handle List Functions +///////////////////////////////////////////////////////////////////////////// + + +// Sets up the object handle list +void CDallasMainDlg::InitObjectHandleList(void) +{ + m_NumObjectHandles=0; +} + +// Clears the object handle list +void CDallasMainDlg::ClearObjectHandleList(void) +{ + m_NumObjectHandles=0; +} + +// Adds a handle to the list +int CDallasMainDlg::AddToObjectHandleList(int handle) +{ + // Is list full? + if(m_NumObjectHandles==MAX_NAMED_OBJECTS) return 0; + + m_ObjectHandleList[m_NumObjectHandles]=handle; + m_NumObjectHandles++; + + return(m_NumObjectHandles-1); +} + + +///////////////////////////////////////////////////////////////////////////// +// Floating Menu Creation Functions +///////////////////////////////////////////////////////////////////////////// + + +// Fills up the given menu with the object categories +// NOTE: Command ID's of objects items start at the given command_offset +void CDallasMainDlg::FillObjectMenu(CMenu *object_menu, int command_offset, bool show_other) +{ + CMenu powerup_submenu, robot_submenu, clutter_submenu, building_submenu, door_submenu, other_submenu; + int powerups_added, robots_added, clutter_added, buildings_added, doors_added, others_added; + int i; + object *objp; + + // Create the category submenus + powerup_submenu.CreatePopupMenu(); + robot_submenu.CreatePopupMenu(); + clutter_submenu.CreatePopupMenu(); + building_submenu.CreatePopupMenu(); + door_submenu.CreatePopupMenu(); + other_submenu.CreatePopupMenu(); + + // Before filling with objects, reset the object handle list + m_NumObjectHandles=0; + + // Set the object counts + powerups_added=0; + robots_added=0; + clutter_added=0; + buildings_added=0; + doors_added=0; + others_added=0; + + // Fill the menus with objects that have custom names + for (i=0,objp=Objects;i<=Highest_object_index;i++,objp++) { + if((m_NumObjectHandles < MAX_NAMED_OBJECTS) && (objp->name) && (objp->type != OBJ_NONE) /*&& (objp->type != OBJ_PLAYER)*/) { + + // Add the object handle to the handle list + m_ObjectHandleList[m_NumObjectHandles]=objp->handle; + + // Add menu item to appropriate submenu + switch(objp->type) { + case OBJ_POWERUP: + powerup_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+m_NumObjectHandles, objp->name); + powerups_added++; + break; + case OBJ_ROBOT: + robot_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+m_NumObjectHandles, objp->name); + robots_added++; + break; + case OBJ_CLUTTER: + clutter_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+m_NumObjectHandles, objp->name); + clutter_added++; + break; + case OBJ_BUILDING: + building_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+m_NumObjectHandles, objp->name); + buildings_added++; + break; + case OBJ_DOOR: + door_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+m_NumObjectHandles, objp->name); + doors_added++; + break; + default: + other_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+m_NumObjectHandles, objp->name); + others_added++; + break; + } + m_NumObjectHandles++; + } + } + + // Add the powerup submenu + ColumnizePopupMenu(&powerup_submenu); + if(powerups_added==0) + object_menu->AppendMenu(MF_POPUP|MF_GRAYED, (unsigned int)powerup_submenu.Detach(), "Powerup"); + else + object_menu->AppendMenu(MF_POPUP, (unsigned int)powerup_submenu.Detach(), "Powerup"); + + // Add the robot submenu + ColumnizePopupMenu(&robot_submenu); + if(robots_added==0) + object_menu->AppendMenu(MF_POPUP|MF_GRAYED, (unsigned int)robot_submenu.Detach(), "Robot"); + else + object_menu->AppendMenu(MF_POPUP, (unsigned int)robot_submenu.Detach(), "Robot"); + + // Add the clutter submenu + ColumnizePopupMenu(&clutter_submenu); + if(clutter_added==0) + object_menu->AppendMenu(MF_POPUP|MF_GRAYED, (unsigned int)clutter_submenu.Detach(), "Clutter"); + else + object_menu->AppendMenu(MF_POPUP, (unsigned int)clutter_submenu.Detach(), "Clutter"); + + // Add the building submenu + ColumnizePopupMenu(&building_submenu); + if(buildings_added==0) + object_menu->AppendMenu(MF_POPUP|MF_GRAYED, (unsigned int)building_submenu.Detach(), "Building"); + else + object_menu->AppendMenu(MF_POPUP, (unsigned int)building_submenu.Detach(), "Building"); + + // Add the door submenu + ColumnizePopupMenu(&door_submenu); + if(doors_added==0) + object_menu->AppendMenu(MF_POPUP|MF_GRAYED, (unsigned int)door_submenu.Detach(), "Door"); + else + object_menu->AppendMenu(MF_POPUP, (unsigned int)door_submenu.Detach(), "Door"); + + // Add the other submenu + ColumnizePopupMenu(&other_submenu); + if(!show_other || others_added==0) + object_menu->AppendMenu(MF_POPUP|MF_GRAYED, (unsigned int)other_submenu.Detach(), "Other"); + else + object_menu->AppendMenu(MF_POPUP, (unsigned int)other_submenu.Detach(), "Other"); +} + + +// Fills up the given menu with the named objects of the specified type +// NOTE: Command ID's of objects items start at the given command_offset +int CDallasMainDlg::FillObjectTypeMenu(CMenu *object_menu, int command_offset, int obj_type) +{ + int objects_added; + int i; + object *objp; + + // Before filling with objects, reset the object handle list + m_NumObjectHandles=0; + + // Set the object counts + objects_added=0; + + // Fill the menus with objects that have custom names + for (i=0,objp=Objects;i<=Highest_object_index;i++,objp++) { + if((m_NumObjectHandles < MAX_NAMED_OBJECTS) && (objp->name) && (objp->type == obj_type)) { + + // Add the object handle to the handle list + m_ObjectHandleList[m_NumObjectHandles]=objp->handle; + + // Add the menu item + object_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+m_NumObjectHandles, objp->name); + objects_added++; + m_NumObjectHandles++; + } + } + + return(objects_added); +} + + +// Fills up the given menu with the named rooms +// NOTE: Command ID's of objects items start at the given command_offset +int CDallasMainDlg::FillRoomMenu(CMenu *room_menu, int command_offset) +{ + int rooms_added; + int i; + room *rp; + + // Set the room count + rooms_added=0; + + // Fill the menus with objects that have custom names + for (i=0,rp=Rooms;i<=Highest_room_index;i++,rp++) { + if((rp->used) && (rp->name)) { + room_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+i, rp->name); + rooms_added++; + } + } + + return(rooms_added); +} + + +// Fills up the given menu with the trigger list +// NOTE: Command ID's of objects items start at the given command_offset +int CDallasMainDlg::FillTriggerMenu(CMenu *trigger_menu, int command_offset) +{ + int t, triggers_added; + trigger *tp; + + // Scan the list, adding triggers to the list + triggers_added=0; + + for (t=0,tp=Triggers;(tname)>0) { + trigger_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+t, tp->name); + triggers_added++; + } + } + + return(triggers_added); +} + + +// Fills up the given menu with the path list +// NOTE: Command ID's of objects items start at the given command_offset +int CDallasMainDlg::FillPathMenu(CMenu *path_menu, int command_offset) +{ + int p, paths_added; + + // Scan the list, adding triggers to the list + paths_added=0; + + for (p=0;p0) { + path_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+p, GamePaths[p].name); + paths_added++; + } + } + + return(paths_added); +} + + +// Fills up the given menu with the matcen list +// NOTE: Command ID's of objects items start at the given command_offset +int CDallasMainDlg::FillMatcenMenu(CMenu *matcen_menu, int command_offset) +{ + int p, matcens_added; + + // Scan the list, adding triggers to the list + matcens_added=0; + + for (p=0;pGetName(matcen_name); + matcen_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+p, matcen_name); + matcens_added++; + } + } + + return(matcens_added); +} + + +// Fills up the given menu with the level goal list +// NOTE: Command ID's of objects items start at the given command_offset +int CDallasMainDlg::FillLevelGoalMenu(CMenu *level_goal_menu, int command_offset) +{ + int p, goals_added, num_goals; + + // Scan the list, adding triggers to the list + goals_added=0; + + num_goals=Level_goals.GetNumGoals(); + for (p=0;p=0) { + level_goal_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+p, goal_name); + goals_added++; + } + } + + return(goals_added); +} + + +// Fills up the given menu with the Script ID List +// NOTE: Command ID's of objects items start at the given command_offset +#define MAX_SCRIPT_MENU_NAME_LEN 32 +int CDallasMainDlg::FillScriptMenu(CMenu *script_menu, int command_offset) +{ + HTREEITEM script_node; + tTreeNodeData *data; + int scripts_added, child_pos; + + // Scan the list, adding each script to the list + scripts_added=0; + child_pos=0; + + script_node=m_ScriptTree.GetChildItem(TVI_ROOT); + while(script_node!=NULL) { + data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_node); + if(data->type==SCRIPT_HEADER_NODE) { + CString menu_string; + FormatTreeText(menu_string,data); + + // Truncate the name (if necessary) so that more will fit + char menu_name[MAX_SCRIPT_MENU_NAME_LEN+3+1]; + strncpy(menu_name,menu_string.GetBuffer(0),MAX_SCRIPT_MENU_NAME_LEN); + menu_name[MAX_SCRIPT_MENU_NAME_LEN]='\0'; + if(menu_string.GetLength() > MAX_SCRIPT_MENU_NAME_LEN) { + strcat(menu_name,"..."); + } + + script_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+child_pos, menu_name); + scripts_added++; + } + script_node=m_ScriptTree.GetNextSiblingItem(script_node); + child_pos++; + } + + return(scripts_added); +} + + +// Fills up the given menu with the logical operations +// NOTE: Command ID's of objects items start at the given command_offset +int CDallasMainDlg::FillLogOpMenu(CMenu *log_op_menu, int command_offset) +{ + int log_ops_added; + + // Scan the list, adding triggers to the list + log_ops_added=0; + log_op_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+AND_TYPE, "AND"); + log_op_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+OR_TYPE, "OR"); + + return(log_ops_added); +} + + +// Fills up the given menu with the appropriate expression operators +// NOTE: Command ID's of objects items start at the given command_offset +int CDallasMainDlg::FillExpOpMenu(CMenu *exp_op_menu, int command_offset, int op_type) +{ + int exp_ops_added=0; + int j; + + // Scan the list, adding triggers to the list + for(j=0;expop_info[j].type>=0;j++) { + if(op_type==expop_info[j].op_type) { + exp_op_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+expop_info[j].type, expop_info[j].menu_name); + exp_ops_added++; + } + else + exp_op_menu->AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, command_offset+expop_info[j].type, expop_info[j].menu_name); + } + + return(exp_ops_added); +} + + +// Fills up the given menu with the literal's available +// NOTE: Command ID's of objects items start at the given command_offset +int CDallasMainDlg::FillLiteralMenu(CMenu *literal_menu, int command_offset, int enum_command_offset, int flag_command_offset, int valid_type, char *valid_name) +{ + CMenu enum_submenu, flag_submenu; + int literals_added, j; + + // Create the enum/flag submenus + enum_submenu.CreatePopupMenu(); + flag_submenu.CreatePopupMenu(); + + int types_added=FillEnumTypesMenu(&enum_submenu,enum_command_offset,valid_name); + int flag_types_added=FillFlagTypesMenu(&flag_submenu,flag_command_offset,valid_name); + + // Scan the list, adding literals + literals_added=0; + + for(j=0;param_menu_item[j].type>=0;j++) { + if(valid_type==ANY_PARAMETER_TYPE || valid_type==param_menu_item[j].type) { + if(j==ENUM_PARAMETER_TYPE) { + ColumnizePopupMenu(&enum_submenu); + if(types_added>0) + literal_menu->AppendMenu(MF_POPUP, (unsigned int)enum_submenu.Detach(), param_menu_item[j].name); + else + literal_menu->AppendMenu(MF_GRAYED | MF_POPUP, (unsigned int)enum_submenu.Detach(), param_menu_item[j].name); + } + else if(j==FLAG_PARAMETER_TYPE) { + ColumnizePopupMenu(&flag_submenu); + if(flag_types_added>0) + literal_menu->AppendMenu(MF_POPUP, (unsigned int)flag_submenu.Detach(), param_menu_item[j].name); + else + literal_menu->AppendMenu(MF_GRAYED | MF_POPUP, (unsigned int)flag_submenu.Detach(), param_menu_item[j].name); + } + else + literal_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+param_menu_item[j].type, param_menu_item[j].name); + literals_added++; + } + else + literal_menu->AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, command_offset+param_menu_item[j].type, param_menu_item[j].name); + } + + return(literals_added); +} + + +// Fills up the given menu with the Condition options +// NOTE: Command ID's of objects items start at the given command_offset +void CDallasMainDlg::FillConditionMenu(CMenu *condition_menu, int command_offset) +{ + int qbin_cmd_offset, qcomp_cmd_offset; + CMenu qbin_submenu, qcomp_submenu; + + if(command_offset==ADD_CONDITION_ID_RANGE_START) { + qbin_cmd_offset=ADD_COND_QBIN_ID_RANGE_START; + qcomp_cmd_offset=ADD_COND_QCOMP_ID_RANGE_START; + } + else { + qbin_cmd_offset=REPLACE_COND_QBIN_ID_RANGE_START; + qcomp_cmd_offset=REPLACE_COND_QCOMP_ID_RANGE_START; + } + + qbin_submenu.CreatePopupMenu(); + FillQueryMenu(&qbin_submenu,qbin_cmd_offset,BOOL_PARAMETER_TYPE,""); + + qcomp_submenu.CreatePopupMenu(); + FillQueryMenu(&qcomp_submenu,qcomp_cmd_offset,ANY_PARAMETER_TYPE,""); + + // Add basic condition types to the list + condition_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+ALWAYS_STATEMENT, ALWAYS_STRING); + condition_menu->AppendMenu(MF_SEPARATOR, 0, ""); + condition_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+BINARY_STATEMENT, "Default Binary Statement"); + condition_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+COMPARISON_STATEMENT, "Default Comparison Statement"); + condition_menu->AppendMenu(MF_SEPARATOR, 0, ""); + + ColumnizePopupMenu(&qbin_submenu); + condition_menu->AppendMenu(MF_POPUP, (unsigned int)qbin_submenu.Detach(), "Binary Statement with Query"); + ColumnizePopupMenu(&qcomp_submenu); + condition_menu->AppendMenu(MF_POPUP, (unsigned int)qcomp_submenu.Detach(), "Comparison Statement with Query"); +} + + +// Creates the Popup menu for the Script Header node +void CDallasMainDlg::DisplayScriptHeaderNodeMenu(POINT *point) +{ + // Create the popup menu + CMenu main_menu; + main_menu.CreatePopupMenu(); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_SPECIFIC_VALUE_ID, "Enter Script Description..."); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); + ColumnizePopupMenu(&main_menu); + main_menu.TrackPopupMenu(0,point->x,point->y,this); + main_menu.DestroyMenu(); +} + + +// Creates the Popup menu for the Script Owner node +void CDallasMainDlg::DisplayScriptOwnerNodeMenu(POINT *point) +{ + // Create the popup menu + int triggers_added; + CMenu main_menu, object_submenu, trigger_submenu; + main_menu.CreatePopupMenu(); + + // Fill the object menu + object_submenu.CreatePopupMenu(); + FillObjectMenu(&object_submenu,ASSIGN_OBJECT_ID_RANGE_START,TRUE); + ColumnizePopupMenu(&object_submenu); + main_menu.AppendMenu(MF_POPUP, (unsigned int)object_submenu.Detach(), "Object"); + + trigger_submenu.CreatePopupMenu(); + triggers_added=FillTriggerMenu(&trigger_submenu,ASSIGN_TRIGGER_ID_RANGE_START); + ColumnizePopupMenu(&trigger_submenu); + if(triggers_added==0) + main_menu.AppendMenu(MF_POPUP|MF_GRAYED, (unsigned int)trigger_submenu.Detach(), "Trigger"); + else + main_menu.AppendMenu(MF_POPUP, (unsigned int)trigger_submenu.Detach(), "Trigger"); + + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_LEVEL_ID, "Level"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); + ColumnizePopupMenu(&main_menu); + main_menu.TrackPopupMenu(0,point->x,point->y,this); + main_menu.DestroyMenu(); +} + + +// Creates the Popup menu for the Script Event node +void CDallasMainDlg::DisplayScriptEventNodeMenu(POINT *point, int owner_type, bool has_a_door_me) +{ + int j; + + // Create the popup menu + CMenu main_menu; + main_menu.CreatePopupMenu(); + + for(j=0;event_info[j].type>=0;j++) { + if + ( + (owner_type==OBJECT_TYPE && (event_info[j].flags & OBJECT_MASK)) || + (owner_type==TRIGGER_TYPE && (event_info[j].flags & TRIGGER_MASK)) || + (owner_type==LEVEL_TYPE && (event_info[j].flags & LEVEL_MASK)) || + (has_a_door_me && (event_info[j].flags & DOOR_OBJECT_MASK)) + ) + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_EVENT_ID_RANGE_START+event_info[j].type, event_info[j].name); + else + main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, ASSIGN_EVENT_ID_RANGE_START+event_info[j].type, event_info[j].name); + } + + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); + + ColumnizePopupMenu(&main_menu); + main_menu.TrackPopupMenu(0,point->x,point->y,this); + main_menu.DestroyMenu(); +} + + +// Creates the Popup menu for the Logical Operator node +void CDallasMainDlg::DisplayLogicalOperatorNodeMenu(POINT *point) +{ + // Create the popup menu + CMenu main_menu, insert_logop_submenu, condition_submenu, add_logop_submenu; + CMenu replace_logop_submenu, replace_condition_submenu; + + insert_logop_submenu.CreatePopupMenu(); + FillLogOpMenu(&insert_logop_submenu,INSERT_LOGOP_ID_RANGE_START); + + condition_submenu.CreatePopupMenu(); + FillConditionMenu(&condition_submenu,ADD_CONDITION_ID_RANGE_START); + + add_logop_submenu.CreatePopupMenu(); + FillLogOpMenu(&add_logop_submenu,ADD_LOGOP_ID_RANGE_START); + + replace_condition_submenu.CreatePopupMenu(); + FillConditionMenu(&replace_condition_submenu,REPLACE_CONDITION_ID_RANGE_START); + + replace_logop_submenu.CreatePopupMenu(); + FillLogOpMenu(&replace_logop_submenu,REPLACE_LOGOP_ID_RANGE_START); + + main_menu.CreatePopupMenu(); + ColumnizePopupMenu(&insert_logop_submenu); + main_menu.AppendMenu(MF_POPUP, (unsigned int)insert_logop_submenu.Detach(), "Insert Logical Operator"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + ColumnizePopupMenu(&condition_submenu); + main_menu.AppendMenu(MF_POPUP, (unsigned int)condition_submenu.Detach(), "Add a New Condition"); + ColumnizePopupMenu(&add_logop_submenu); + main_menu.AppendMenu(MF_POPUP, (unsigned int)add_logop_submenu.Detach(), "Add Logical Operator"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + ColumnizePopupMenu(&replace_condition_submenu); + main_menu.AppendMenu(MF_POPUP, (unsigned int)replace_condition_submenu.Detach(), "Replace with a Condition"); + ColumnizePopupMenu(&replace_logop_submenu); + main_menu.AppendMenu(MF_POPUP, (unsigned int)replace_logop_submenu.Detach(), "Replace with a New Logical Operator"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, DELETE_ALL_ID, "Delete this Operator"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); + + ColumnizePopupMenu(&main_menu); + main_menu.TrackPopupMenu(0,point->x,point->y,this); + main_menu.DestroyMenu(); +} + + +// Creates the Popup menu for the Conditional Statement node +void CDallasMainDlg::DisplayConditionalStatementNodeMenu(POINT *point) +{ + // Create the popup menu + CMenu main_menu, log_op_submenu; + CMenu replace_logop_submenu, replace_condition_submenu; + + log_op_submenu.CreatePopupMenu(); + FillLogOpMenu(&log_op_submenu,INSERT_LOGOP_ID_RANGE_START); + + replace_condition_submenu.CreatePopupMenu(); + FillConditionMenu(&replace_condition_submenu,REPLACE_CONDITION_ID_RANGE_START); + + replace_logop_submenu.CreatePopupMenu(); + FillLogOpMenu(&replace_logop_submenu,REPLACE_LOGOP_ID_RANGE_START); + + main_menu.CreatePopupMenu(); + ColumnizePopupMenu(&log_op_submenu); + main_menu.AppendMenu(MF_POPUP, (unsigned int)log_op_submenu.Detach(), "Insert Logical Operator"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + ColumnizePopupMenu(&replace_condition_submenu); + main_menu.AppendMenu(MF_POPUP, (unsigned int)replace_condition_submenu.Detach(), "Replace with a New Condition"); + ColumnizePopupMenu(&replace_logop_submenu); + main_menu.AppendMenu(MF_POPUP, (unsigned int)replace_logop_submenu.Detach(), "Replace with a Logical Operator"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, DELETE_ALL_ID, "Delete this Condition"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); + + ColumnizePopupMenu(&main_menu); + main_menu.TrackPopupMenu(0,point->x,point->y,this); + main_menu.DestroyMenu(); +} + + +// Creates the Popup menu for the Expression node +void CDallasMainDlg::DisplayExpressionNodeMenu(POINT *point, int valid_return_type, char *valid_return_name) +{ + CMenu main_menu, replace_with_query_submenu, replace_with_literal_submenu; + + replace_with_query_submenu.CreatePopupMenu(); + FillQueryMenu(&replace_with_query_submenu,REPLACE_QUERY_ID_RANGE_START,valid_return_type,valid_return_name); + + replace_with_literal_submenu.CreatePopupMenu(); + FillLiteralMenu(&replace_with_literal_submenu,REPLACE_LITERAL_ID_RANGE_START,REPLACE_LIT_ENUM_ID_RANGE_START,REPLACE_LIT_FLAG_ID_RANGE_START,valid_return_type,valid_return_name); + + main_menu.CreatePopupMenu(); + ColumnizePopupMenu(&replace_with_query_submenu); + main_menu.AppendMenu(MF_POPUP, (unsigned int)replace_with_query_submenu.Detach(), "Replace with Query"); + ColumnizePopupMenu(&replace_with_literal_submenu); + main_menu.AppendMenu(MF_POPUP, (unsigned int)replace_with_literal_submenu.Detach(), "Replace with Literal"); + + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); + ColumnizePopupMenu(&main_menu); + main_menu.TrackPopupMenu(0,point->x,point->y,this); + main_menu.DestroyMenu(); + +} + + +// Creates the Popup menu for the Expression Operator node +void CDallasMainDlg::DisplayExpressionOperatorNodeMenu(POINT *point, int op_type) +{ + CMenu main_menu; + main_menu.CreatePopupMenu(); + + FillExpOpMenu(&main_menu,ASSIGN_EXPOP_ID_RANGE_START,op_type); + + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); + ColumnizePopupMenu(&main_menu); + main_menu.TrackPopupMenu(0,point->x,point->y,this); + main_menu.DestroyMenu(); +} + + +// Creates the Popup menu for the Action Statement node +void CDallasMainDlg::DisplayActionStatementNodeMenu(POINT *point) +{ + // Create the popup menu + CMenu main_menu; + CMenu insert_actions_submenu, replace_actions_submenu; + + insert_actions_submenu.CreatePopupMenu(); + insert_actions_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ADD_DO_NOTHING_ACTION_ID, DO_NOTHING_STRING); + insert_actions_submenu.AppendMenu(MF_SEPARATOR, 0, ""); + FillActionMenu(&insert_actions_submenu,ADD_ACTION_ID_RANGE_START); + + replace_actions_submenu.CreatePopupMenu(); + replace_actions_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, REPLACE_DO_NOTHING_ACTION_ID, DO_NOTHING_STRING); + replace_actions_submenu.AppendMenu(MF_SEPARATOR, 0, ""); + FillActionMenu(&replace_actions_submenu,REPLACE_ACTION_ID_RANGE_START); + + main_menu.CreatePopupMenu(); + ColumnizePopupMenu(&insert_actions_submenu); + main_menu.AppendMenu(MF_POPUP, (unsigned int)insert_actions_submenu.Detach(), "Insert a New Action"); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ADD_IF_THEN_CLAUSE_ID, "Insert a Nested IF-THEN Clause"); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ADD_IF_THEN_ELSE_CLAUSE_ID, "Insert a Nested IF-THEN-ELSE Clause"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + ColumnizePopupMenu(&replace_actions_submenu); + main_menu.AppendMenu(MF_POPUP, (unsigned int)replace_actions_submenu.Detach(), "Replace with a Different Action"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, DELETE_ALL_ID, "Delete"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); + + ColumnizePopupMenu(&main_menu); + main_menu.TrackPopupMenu(0,point->x,point->y,this); + main_menu.DestroyMenu(); +} + + +// Creates the Popup menu for the Action Header node +void CDallasMainDlg::DisplayActionHeaderNodeMenu(POINT *point, int level_type, int clause_type, bool can_add_else) +{ + // Create the popup menu + CMenu main_menu, add_actions_submenu, select_extimes_submenu, select_chain_submenu; + + add_actions_submenu.CreatePopupMenu(); + add_actions_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ADD_DO_NOTHING_ACTION_ID, DO_NOTHING_STRING); + add_actions_submenu.AppendMenu(MF_SEPARATOR, 0, ""); + FillActionMenu(&add_actions_submenu,ADD_ACTION_ID_RANGE_START); + + select_extimes_submenu.CreatePopupMenu(); + select_extimes_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_EXEC_TIME_ID_RANGE_START+ENTER_EXEC_TIMES, "Enter number of times..."); + select_extimes_submenu.AppendMenu(MF_SEPARATOR, 0, ""); + select_extimes_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_EXEC_TIME_ID_RANGE_START+EXECUTE_INFINITELY, "Run Infinitely"); + select_extimes_submenu.AppendMenu(MF_SEPARATOR, 0, ""); + select_extimes_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_EXEC_TIME_ID_RANGE_START+EXECUTE_ONCE, "Once"); + select_extimes_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_EXEC_TIME_ID_RANGE_START+EXECUTE_TWICE, "Twice"); + + select_chain_submenu.CreatePopupMenu(); + select_chain_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_CHAIN_ID_RANGE_START+CONTINUE_SCRIPT_CHAIN, "Continue the Script Chain (DEFAULT)"); + select_chain_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_CHAIN_ID_RANGE_START+BREAK_SCRIPT_CHAIN, "Break the Script Chain"); + + main_menu.CreatePopupMenu(); + ColumnizePopupMenu(&select_extimes_submenu); + if(level_type==TOP_LEVEL) + main_menu.AppendMenu(MF_POPUP, (unsigned int)select_extimes_submenu.Detach(), "Select Max Times to Execute"); + else + main_menu.AppendMenu(MF_GRAYED|MF_POPUP, (unsigned int)select_extimes_submenu.Detach(), "Select Max Times to Execute"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + if(level_type==TOP_LEVEL) + main_menu.AppendMenu(MF_POPUP, (unsigned int)select_chain_submenu.Detach(), "Select Script Chaining Option"); + else + main_menu.AppendMenu(MF_GRAYED|MF_POPUP, (unsigned int)select_chain_submenu.Detach(), "Select Script Chaining Option"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + ColumnizePopupMenu(&add_actions_submenu); + main_menu.AppendMenu(MF_POPUP, (unsigned int)add_actions_submenu.Detach(), "Add a New Action"); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ADD_IF_THEN_CLAUSE_ID, "Add a Nested IF-THEN Clause"); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ADD_IF_THEN_ELSE_CLAUSE_ID, "Add a Nested IF-THEN-ELSE Clause"); + if(can_add_else) + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ADD_ELSE_CLAUSE_ID, "Append an ELSE to this Clause"); + else + main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, ADD_ELSE_CLAUSE_ID, "Append an ELSE to this Clause"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, DELETE_CHILDREN_ONLY_ID, "Delete all Child Actions and Clauses"); + if(level_type==TOP_LEVEL) + main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, DELETE_ALL_ID, "Delete this Entire IF-THEN Clause"); + else { + if(clause_type==THEN_CLAUSE) + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, DELETE_ALL_ID, "Delete this Entire IF-THEN Clause"); + else + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, DELETE_ALL_ID, "Delete this Else Clause"); + } + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); + + ColumnizePopupMenu(&main_menu); + main_menu.TrackPopupMenu(0,point->x,point->y,this); + main_menu.DestroyMenu(); +} + + +// Displays the popup menus for the various parameter types +void CDallasMainDlg::DisplayParameterNodeMenu(POINT *point, int param_type, char *param_name, int valid_return_type, char *valid_return_name, bool has_an_it, bool has_a_me, bool has_a_door_me, bool has_a_goalID, bool has_a_timerID, bool has_a_matcenID, bool has_a_levgoalID) +{ + CMenu main_menu, replace_with_query_submenu, replace_with_literal_submenu; + + replace_with_query_submenu.CreatePopupMenu(); + FillQueryMenu(&replace_with_query_submenu,REPLACE_QUERY_ID_RANGE_START,valid_return_type,valid_return_name); + + replace_with_literal_submenu.CreatePopupMenu(); + FillLiteralMenu(&replace_with_literal_submenu,REPLACE_LITERAL_ID_RANGE_START,REPLACE_LIT_ENUM_ID_RANGE_START,REPLACE_LIT_FLAG_ID_RANGE_START,valid_return_type,valid_return_name); + + main_menu.CreatePopupMenu(); + + switch(param_type) { + case DOOR_PARAMETER_TYPE: + { + if(has_a_door_me) + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_OBJECT_ME_ID, "OWNER"); + else + main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING,ASSIGN_OBJECT_ME_ID, "OWNER"); + + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + FillObjectTypeMenu(&main_menu,ASSIGN_OBJECT_ID_RANGE_START,OBJ_DOOR); + } + break; + case OBJECT_PARAMETER_TYPE: + { + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_OBJECT_NONE_ID,NONE_STRING); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + + if(has_a_me) + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_OBJECT_ME_ID, "OWNER"); + else + main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING,ASSIGN_OBJECT_ME_ID, "OWNER"); + + if(has_an_it) + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_OBJECT_IT_ID, "IT"); + else + main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING,ASSIGN_OBJECT_IT_ID, "IT"); + + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + FillObjectMenu(&main_menu,ASSIGN_OBJECT_ID_RANGE_START,TRUE); + } + break; + case ROOM_PARAMETER_TYPE: + { + FillRoomMenu(&main_menu,ASSIGN_ROOM_ID_RANGE_START); + } + break; + case TRIGGER_PARAMETER_TYPE: + { + FillTriggerMenu(&main_menu,ASSIGN_TRIGGER_ID_RANGE_START); + } + break; + case INT_PARAMETER_TYPE: + { + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_SPECIFIC_VALUE_ID, "Enter Integer Value..."); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + } + break; + case BOOL_PARAMETER_TYPE: + { + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_TRUE_ID, "TRUE"); + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_FALSE_ID, "FALSE"); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + } + break; + case FLOAT_PARAMETER_TYPE: + { + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_SPECIFIC_VALUE_ID, "Enter Float Value..."); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + } + break; + case VECTOR_PARAMETER_TYPE: + { + main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_SPECIFIC_VALUE_ID, "Enter Vector Values..."); + main_menu.AppendMenu(MF_SEPARATOR, 0, ""); + } + break; + case STRING_PARAMETER_TYPE: + { + int j, num_msgs; + + // Fill list with Message ID Names + num_msgs=m_MessageList.GetCount(); + for(j=0;jx,point->y,this); + main_menu.DestroyMenu(); +} + + +// Takes the given popup menu and breaks it into columns +void CDallasMainDlg::ColumnizePopupMenu(CMenu *menu) +{ + int screen_height, menu_item_height; + int item_count; + int items_per_column; + int pos; + + if(menu==NULL) return; + + item_count=menu->GetMenuItemCount(); + if(item_count==0) return; + + screen_height=GetSystemMetrics(SM_CYSCREEN); + menu_item_height=GetSystemMetrics(SM_CYMENU); + if(menu_item_height>0) + items_per_column=screen_height/menu_item_height; + else + items_per_column=25; + + // Clip the items per column to a min and max if necessary + if(items_per_column<25) items_per_column=25; + if(items_per_column>40) items_per_column=40; + + pos=items_per_column; + while(posGetMenuString(pos,name,MF_BYPOSITION); + + // Set the default flags + flags=MF_BYPOSITION|MF_MENUBARBREAK; + + state=menu->GetMenuState(pos,MF_BYPOSITION); + if(state & MF_GRAYED) flags |= MF_GRAYED; + if(state & MF_ENABLED) flags |= MF_ENABLED; + if(state & MF_UNCHECKED) flags |= MF_UNCHECKED; + + // Get the item ID + id=menu->GetMenuItemID(pos); + if(id==0) { // is it a separator? + flags |= MF_SEPARATOR; + id=0; + } + else if(id==-1) { // is it a popup? + CMenu *submenu; + + submenu=menu->GetSubMenu(pos); + if(submenu!=NULL) { + id=(unsigned int)submenu->Detach(); + flags |= MF_POPUP; + } + } + + if(name.IsEmpty()) + menu->ModifyMenu(pos,flags,id); + else + menu->ModifyMenu(pos,flags,id,name.GetBuffer(0)); + + pos+=items_per_column; + } +} + + +///////////////////////////////////////////////////////////////////////////// +// Functions to Assign Values To Data Nodes +///////////////////////////////////////////////////////////////////////////// + + +// Obtains the appropriate script ID +void CDallasMainDlg::AssignScriptID(int pos) +{ + HTREEITEM selected_node; + tTreeNodeData *data; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Handle entering Script Header node descriptions + if(data->type==PARAMETER_NODE && data->ID==SCRIPT_PARAMETER_TYPE) { + HTREEITEM script_node; + script_node=GetNthChild(TVI_ROOT,pos+1); + if(script_node==NULL) return; + + data->int_val=GetScriptID(script_node); + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + } +} + + +// Obtains the appropriate data through popup dialogs +void CDallasMainDlg::AssignExecTime(int ID) +{ + HTREEITEM selected_node; + tTreeNodeData *data; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Handle entering Script Header node descriptions + if(data->type==ACTIONS_HEADER_NODE && data->ID==TOP_LEVEL) { + switch(ID) { + case ENTER_EXEC_TIMES: + { + CDallasGenericPromptDlg dlg; + + // Display the prompt dialog + dlg.m_DialogTitle="Maximum Execution Times Prompt"; + dlg.m_PromptText="Enter the maximum times to execute script:"; + dlg.m_PromptData.Format("%d",data->subID); + dlg.m_MaxDataLength=MAX_NDATA_NAME_LEN; + + if(dlg.DoModal()==IDCANCEL) return; + + data->subID=atoi(dlg.m_PromptData.GetBuffer(0)); + } + break; + case EXECUTE_INFINITELY: + data->subID=0; + break; + case EXECUTE_ONCE: + data->subID=1; + break; + case EXECUTE_TWICE: + data->subID=2; + break; + } + UpdateNodeText(selected_node); + SetModified(TRUE); + } +} + + +// Sets the chain option for the action header +void CDallasMainDlg::AssignChainOption(int ID) +{ + HTREEITEM selected_node; + tTreeNodeData *data; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Handle entering Script Header node descriptions + if(data->type==ACTIONS_HEADER_NODE && data->ID==TOP_LEVEL) { + data->int_val=ID; + UpdateNodeText(selected_node); + SetModified(TRUE); + } +} + + +// Obtains the appropriate data through popup dialogs +void CDallasMainDlg::AssignSpecificValue(void) +{ + HTREEITEM selected_node; + tTreeNodeData *data; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Handle entering Script Header node descriptions + if(data->type==SCRIPT_HEADER_NODE) { + + CDallasGenericPromptDlg dlg; + + // Display the prompt dialog + dlg.m_DialogTitle="Script Description Prompt"; + dlg.m_PromptText="Enter the new script description:"; + dlg.m_PromptData=data->name; + dlg.m_MaxDataLength=MAX_NDATA_NAME_LEN; + + if(dlg.DoModal()==IDCANCEL) return; + + strncpy(data->name,dlg.m_PromptData.GetBuffer(0),MAX_NDATA_NAME_LEN); + data->name[MAX_NDATA_NAME_LEN]='\0'; + UpdateNodeText(selected_node); + SetModified(TRUE); + return; + } + + // Handle entering a Parameter Int value + if(data->type==PARAMETER_NODE && data->ID==INT_PARAMETER_TYPE) { + + CDallasGenericPromptDlg dlg; + + // Display the prompt dialog + dlg.m_DialogTitle="Integer Value Prompt"; + dlg.m_PromptText.Format("Enter value for %s (integer):",data->name); + dlg.m_PromptData.Format("%d",data->int_val); + dlg.m_MaxDataLength=MAX_NDATA_NAME_LEN; + + if(dlg.DoModal()==IDCANCEL) return; + + int value=atoi(dlg.m_PromptData.GetBuffer(0)); + + // If a range is specified, verify that entered value is in it + CString name_text, default_text, range_text; + int n, param_type; + n=GetChildPosition(selected_node); + param_type=ParseNthParam(m_ScriptTree.GetParentItem(selected_node),n,name_text,default_text,range_text); + if(param_type>=0 && !range_text.IsEmpty()) { + if(!VerifyIntegerRange(value,range_text.GetBuffer(0))) { + CString msg; + msg.Format("That value is outside the legal range (%s) for this parameter!",range_text); + MessageBox(msg,"Invalid Value Entered",MB_OK|MB_ICONEXCLAMATION); + return; + } + } + + data->int_val=value; + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + return; + } + + // Handle entering a Parameter Float value + if(data->type==PARAMETER_NODE && data->ID==FLOAT_PARAMETER_TYPE) { + + CDallasGenericPromptDlg dlg; + + // Display the prompt dialog + dlg.m_DialogTitle="Float Value Prompt"; + dlg.m_PromptText.Format("Enter value for %s (float):",data->name); + dlg.m_PromptData.Format("%f",data->float_val1); + dlg.m_MaxDataLength=MAX_NDATA_NAME_LEN; + + if(dlg.DoModal()==IDCANCEL) return; + + float value=atof(dlg.m_PromptData.GetBuffer(0)); + + // If a range is specified, verify that entered value is in it + CString name_text, default_text, range_text; + int n, param_type; + n=GetChildPosition(selected_node); + param_type=ParseNthParam(m_ScriptTree.GetParentItem(selected_node),n,name_text,default_text,range_text); + if(param_type>=0 && !range_text.IsEmpty()) { + if(!VerifyFloatRange(value,range_text.GetBuffer(0))) { + CString msg; + msg.Format("That value is outside the legal range (%s) for this parameter!",range_text); + MessageBox(msg,"Invalid Value Entered",MB_OK|MB_ICONEXCLAMATION); + return; + } + } + + data->float_val1=value; + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + return; + } + + // Handle entering a Parameter Vector value + if(data->type==PARAMETER_NODE && data->ID==VECTOR_PARAMETER_TYPE) { + + CDallasVectorPromptDialog dlg; + + // Display the prompt dialog + dlg.m_PromptData1=data->float_val1; + dlg.m_PromptData2=data->float_val2; + dlg.m_PromptData3=data->float_val3; + + if(dlg.DoModal()==IDCANCEL) return; + + data->float_val1=dlg.m_PromptData1; + data->float_val2=dlg.m_PromptData2; + data->float_val3=dlg.m_PromptData3; + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + return; + } + + // Handle entering a Sound value + if(data->type==PARAMETER_NODE && data->ID==SOUND_PARAMETER_TYPE) { + + CDallasSoundDlg dlg; + + // Display the prompt dialog + if(data->int_val>=0 && data->int_valint_val].used) + dlg.m_SoundName=Sounds[data->int_val].name; + + if(dlg.DoModal()==IDCANCEL) return; + + if(dlg.m_SoundIndex>=0 && dlg.m_SoundIndexint_val=dlg.m_SoundIndex; + strncpy(data->str_val,Sounds[data->int_val].name,MAX_MESSAGE_NAME_LEN); + data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; + } + + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + return; + } + + // Handle entering a Streaming Audio value + if(data->type==PARAMETER_NODE && data->ID==STRM_AUDIO_PARAMETER_TYPE) { + + CDallasStrmAudioDlg dlg; + + // Display the prompt dialog + if(strlen(data->str_val)>0) + dlg.m_Filename=data->str_val; + + if(dlg.DoModal()==IDCANCEL) return; + + if(!dlg.m_Filename.IsEmpty()) { + strncpy(data->str_val,dlg.m_Filename.GetBuffer(0),MAX_MESSAGE_NAME_LEN); + data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; + } + + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + return; + } + + // Handle entering a Texture value + if(data->type==PARAMETER_NODE && data->ID==TEXTURE_PARAMETER_TYPE) { + + CDallasTextureDlg dlg; + + // Display the prompt dialog + if(data->int_val>=0 && data->int_valint_val].used) + dlg.m_TextureName=GameTextures[data->int_val].name; + + if(dlg.DoModal()==IDCANCEL) return; + + if(dlg.m_TextureIndex>=0 && dlg.m_TextureIndexint_val=dlg.m_TextureIndex; + strncpy(data->str_val,GameTextures[data->int_val].name,MAX_MESSAGE_NAME_LEN); + data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; + } + + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + return; + } + + // Handle entering a Flag value + if(data->type==PARAMETER_NODE && data->ID==FLAG_PARAMETER_TYPE) { + + CDallasFlagDlg dlg; + + // Display the prompt dialog + dlg.m_FlagsValue=data->int_val; + dlg.m_FlagsName=data->name; + + // Get the range (contains valid flags mask) + CString name_text, default_text, range_text; + int n, param_type; + n=GetChildPosition(selected_node); + param_type=ParseNthParam(m_ScriptTree.GetParentItem(selected_node),n,name_text,default_text,range_text); + if(param_type>=0 && !range_text.IsEmpty()) { + dlg.m_ValidFlagsMask=atoi(range_text.GetBuffer(0)); + } + + if(dlg.DoModal()==IDCANCEL) return; + + data->int_val=dlg.m_FlagsValue; + + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + return; + } + + // Handle entering a Specific Name + if(data->type==PARAMETER_NODE && data->ID==SPECNAME_PARAMETER_TYPE) { + + CDallasGenericPromptDlg dlg; + + // Display the prompt dialog + dlg.m_DialogTitle="Specific Name Prompt"; + dlg.m_PromptText.Format("Enter the specific name for %s:",data->name); + dlg.m_PromptData=data->str_val; + dlg.m_MaxDataLength=MAX_MESSAGE_NAME_LEN; + + if(dlg.DoModal()==IDCANCEL) return; + + // Check if the message name is valid + char *newname=dlg.m_PromptData.GetBuffer(0); + if(strlen(newname)==0) return; + for(unsigned int j=0;jstr_val,newname,MAX_MESSAGE_NAME_LEN); + data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + return; + } + + + // Handle entering a Parameter Vector value + if(data->type==PARAMETER_NODE && data->ID==PERCENTAGE_PARAMETER_TYPE) { + + CDallasGenericPromptDlg dlg; + + // Display the prompt dialog + dlg.m_DialogTitle="Percent Value Prompt"; + dlg.m_PromptText.Format("Enter data for %s (as a percentage):",data->name); + dlg.m_PromptData.Format("%f",data->float_val1*100.0); + dlg.m_MaxDataLength=MAX_NDATA_NAME_LEN; + + if(dlg.DoModal()==IDCANCEL) return; + + float value=atof(dlg.m_PromptData.GetBuffer(0))/100.0; + + // If a range is specified, verify that entered value is in it + CString name_text, default_text, range_text; + int n, param_type; + n=GetChildPosition(selected_node); + param_type=ParseNthParam(m_ScriptTree.GetParentItem(selected_node),n,name_text,default_text,range_text); + if(param_type>=0 && !range_text.IsEmpty()) { + if(!VerifyFloatRange(value,range_text.GetBuffer(0))) { + CString msg; + msg.Format("That value is outside the legal range (%s) for this parameter!",range_text); + MessageBox(msg,"Invalid Value Entered",MB_OK|MB_ICONEXCLAMATION); + return; + } + } + + data->float_val1=value; + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + return; + } + + // If we're here, then no popup dialog could be displayed, + // so, instead, display the popup menu for the selected node + RECT rect; + if(m_ScriptTree.GetItemRect(selected_node,&rect,TRUE)) { + POINT pt; + + pt.x=rect.left; + pt.y=(rect.top+rect.bottom)/2; + m_ScriptTree.ClientToScreen(&pt); + + DisplayFloatingPopupMenu(selected_node,pt); + } +} + + +// Assigns an owner to a Script Owner Node +void CDallasMainDlg::AssignNamedValue(int type, int handle) +{ + HTREEITEM selected_node; + tTreeNodeData *data; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // If it's a script event node, then process accordingly + if(data->type == SCRIPT_OWNER_NODE) { + int old_type=data->ID; + data->ID=type; + switch(type) { + case LEVEL_TYPE: + data->int_val=handle; + if(old_type!=LEVEL_TYPE) + SetScriptEventType(selected_node,LEVEL_START_EVENT_TYPE); + break; + case OBJECT_TYPE: + if(handle==OBJECT_NONE_HANDLE) { + data->int_val=OBJECT_HANDLE_NONE; + data->subID=USE_OBJECT_HANDLE; + strcpy(data->str_val,""); + } + else { + data->int_val=m_ObjectHandleList[handle]; + data->subID=USE_OBJECT_HANDLE; + object *objp=ObjGet(data->int_val); + if(objp!=NULL && objp->name!=NULL) { + strncpy(data->str_val,objp->name,MAX_MESSAGE_NAME_LEN); + data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; + } + else + strcpy(data->str_val,""); + if(old_type!=OBJECT_TYPE) + SetScriptEventType(selected_node,COLLIDE_EVENT_TYPE); + } + break; + case TRIGGER_TYPE: + data->int_val=handle; + if(data->int_val<0 || data->int_val>=Num_triggers) + strcpy(data->str_val,""); + else { + strncpy(data->str_val,Triggers[data->int_val].name,MAX_MESSAGE_NAME_LEN); + data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; + } + if(old_type!=TRIGGER_TYPE) + SetScriptEventType(selected_node,ACTIVATED_EVENT_TYPE); + break; + } + UpdateNodeText(selected_node); + SetModified(TRUE); + HighlightScript(selected_node); + } + + // If it's a parameter node, then process accordingly + if(data->type == PARAMETER_NODE) { + switch(type) { + case OBJECT_TYPE: + if(data->ID == OBJECT_PARAMETER_TYPE) { + if(handle==OBJECT_NONE_HANDLE) { + data->int_val=OBJECT_HANDLE_NONE; + data->subID=USE_OBJECT_HANDLE; + strcpy(data->str_val,""); + } + else if(handle==OBJECT_ME_HANDLE) { + data->int_val=OBJECT_HANDLE_NONE; + data->subID=USE_ME_HANDLE; + strcpy(data->str_val,""); + } + else if(handle==OBJECT_IT_HANDLE) { + data->int_val=OBJECT_HANDLE_NONE; + data->subID=USE_IT_HANDLE; + strcpy(data->str_val,""); + } + else { + data->int_val=m_ObjectHandleList[handle]; + data->subID=USE_OBJECT_HANDLE; + object *objp=ObjGet(data->int_val); + if(objp!=NULL && objp->name!=NULL) { + strncpy(data->str_val,objp->name,MAX_MESSAGE_NAME_LEN); + data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; + } + else + strcpy(data->str_val,""); + } + } + else if(data->ID == DOOR_PARAMETER_TYPE) { + if(handle==OBJECT_NONE_HANDLE) { + data->int_val=OBJECT_HANDLE_NONE; + data->subID=USE_OBJECT_HANDLE; + strcpy(data->str_val,""); + } + else if(handle==OBJECT_ME_HANDLE) { + data->int_val=OBJECT_HANDLE_NONE; + data->subID=USE_ME_HANDLE; + strcpy(data->str_val,""); + } + else { + data->int_val=m_ObjectHandleList[handle]; + data->subID=USE_OBJECT_HANDLE; + object *objp=ObjGet(data->int_val); + if(objp!=NULL && objp->name!=NULL) { + strncpy(data->str_val,objp->name,MAX_MESSAGE_NAME_LEN); + data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; + } + else + strcpy(data->str_val,""); + } + } + break; + case TRIGGER_TYPE: + if(data->ID == TRIGGER_PARAMETER_TYPE) { + data->int_val=handle; + if(data->int_val<0 || data->int_val>=Num_triggers) + strcpy(data->str_val,""); + else { + strncpy(data->str_val,Triggers[data->int_val].name,MAX_MESSAGE_NAME_LEN); + data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; + } + } + break; + case ROOM_TYPE: + if(data->ID == ROOM_PARAMETER_TYPE) { + data->int_val=handle; + if(data->int_val<0 || data->int_val>Highest_room_index) + strcpy(data->str_val,""); + else { + strncpy(data->str_val,Rooms[data->int_val].name,MAX_MESSAGE_NAME_LEN); + data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; + } + } + break; + case PATH_TYPE: + if(data->ID == PATH_PARAMETER_TYPE) { + data->int_val=handle; + if(data->int_val<0 || data->int_val>=MAX_GAME_PATHS || !GamePaths[data->int_val].used) + strcpy(data->str_val,""); + else { + strncpy(data->str_val,GamePaths[data->int_val].name,MAX_MESSAGE_NAME_LEN); + data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; + } + } + break; + case MATCEN_TYPE: + if(data->ID == MATCEN_PARAMETER_TYPE) { + if(handle==MATCEN_ID_VALUE) { + data->subID=USE_MATCEN_EVENT_ID; + data->int_val=0; + strcpy(data->str_val,""); + } + else { + data->subID=USE_MATCEN_VALUE; + data->int_val=handle; + if(!MatcenValid(data->int_val)) + strcpy(data->str_val,""); + else { + char matcen_name[MAX_MATCEN_NAME_LEN+1]; + Matcen[data->int_val]->GetName(matcen_name); + strncpy(data->str_val,matcen_name,MAX_MESSAGE_NAME_LEN); + data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; + } + } + } + break; + case LEVEL_GOAL_TYPE: + if(data->ID == LEVEL_GOAL_PARAMETER_TYPE) { + if(handle==LEVEL_GOAL_ID_VALUE) { + data->subID=USE_LEVEL_GOAL_ID; + data->int_val=0; + strcpy(data->str_val,""); + } + else { + char goal_name[MAX_PATH+1]; + data->subID=USE_LEVEL_GOAL_VALUE; + data->int_val=handle; + if(Level_goals.GoalGetName(data->int_val,goal_name,MAX_PATH)<0) + strcpy(data->str_val,""); + else { + strncpy(data->str_val,goal_name,MAX_MESSAGE_NAME_LEN); + data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; + } + } + } + break; + } + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + } +} + + +// Assigns an event type to a Script Event Node +void CDallasMainDlg::AssignEventType(int type) +{ + HTREEITEM selected_node; + tTreeNodeData *data; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Make sure it's a script event node + if(data->type == SCRIPT_EVENT_NODE) { + data->ID=type; + UpdateNodeText(selected_node); + SetModified(TRUE); + } +} + + +// Assigns a boolean type to a Bool parameter +void CDallasMainDlg::AssignBooleanValue(int type) +{ + HTREEITEM selected_node; + tTreeNodeData *data; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Make sure it's a boolean parameter node + if(data->type == PARAMETER_NODE && data->ID == BOOL_PARAMETER_TYPE) { + data->int_val=type; + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + } +} + + +// Assigns a message name +void CDallasMainDlg::AssignMessageName(int msg_ID) +{ + HTREEITEM selected_node; + tTreeNodeData *data; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Make sure it's a boolean parameter node + if(data->type == PARAMETER_NODE && data->ID == STRING_PARAMETER_TYPE) { + CString msg_name; + m_MessageList.GetText(msg_ID,msg_name); + strncpy(data->str_val,msg_name.GetBuffer(0),MAX_MESSAGE_NAME_LEN); + data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + } +} + + +// Assigns an expression operator type +void CDallasMainDlg::AssignExpOpType(int type) +{ + HTREEITEM selected_node; + tTreeNodeData *data; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Make sure it's a script event node + if(data->type == EXPRESSION_OPERATOR_NODE) { + data->subID=type; + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + } +} + + +// Assigns an expression operator type +void CDallasMainDlg::AssignEnumValueType(int type) +{ + HTREEITEM selected_node; + tTreeNodeData *data; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Make sure it's a parameter-enum node + if(data->type == PARAMETER_NODE && data->ID==ENUM_PARAMETER_TYPE) { + + if(type==ENUM_GOALID_VALUE) { + data->subID=USE_GOALID_VALUE; + data->int_val=0; + } + else if(type==ENUM_TIMERID_VALUE) { + data->subID=USE_TIMERID_VALUE; + data->int_val=0; + } + else if(type==ENUM_MATCENID_VALUE) { + data->subID=USE_MATCENID_VALUE; + data->int_val=0; + } + else { + int DBslot; + + DBslot=GetEnumID(data->name); + if(DBslot==INVALID_ENUM) return; + + if(type<0 || type>=m_EnumDatabase[DBslot].num_values) return; + data->int_val=m_EnumDatabase[DBslot].values[type].value; + data->subID=USE_ENUM_VALUE; + } + + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + } +} + + +///////////////////////////////////////////////////////////////////////////// +// Functions to Add Tree Nodes (specific types) +///////////////////////////////////////////////////////////////////////////// + + +// Adds nested IF-THEN Clause +void CDallasMainDlg::AddNestedIfThenClause(void) +{ + HTREEITEM selected_node; + tTreeNodeData *data; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Add node appropriately with respect to selected node + if(data->type==ACTIONS_HEADER_NODE) { + CreateDefaultIfThenClause(selected_node,TVI_LAST,NESTED); + m_ScriptTree.Expand(selected_node,TVE_EXPAND); + } + else { + CreateDefaultIfThenClause(m_ScriptTree.GetParentItem(selected_node),selected_node,NESTED); + m_ScriptTree.Expand(m_ScriptTree.GetParentItem(selected_node),TVE_EXPAND); + } + SetModified(TRUE); +} + + +// Adds nested ELSE Clause +void CDallasMainDlg::AddNestedElseClause(void) +{ + HTREEITEM selected_node, next_node; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Add node appropriately with respect to selected node + if(!CanAppendElseToNode(selected_node)) return; + + // See if there is a node after this one + next_node=m_ScriptTree.GetNextSiblingItem(selected_node); + + if(next_node==NULL) + CreateDefaultElseClause(m_ScriptTree.GetParentItem(selected_node),TVI_LAST); + else + CreateDefaultElseClause(m_ScriptTree.GetParentItem(next_node),next_node); + SetModified(TRUE); +} + + +// Adds nested IF-THEN-ELSE Clause +void CDallasMainDlg::AddNestedIfThenElseClause(void) +{ + HTREEITEM selected_node; + tTreeNodeData *data; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Add node appropriately with respect to selected node + if(data->type==ACTIONS_HEADER_NODE) { + CreateDefaultIfThenClause(selected_node,TVI_LAST,NESTED); + CreateDefaultElseClause(selected_node,TVI_LAST); + m_ScriptTree.Expand(selected_node,TVE_EXPAND); + } + else { + CreateDefaultIfThenClause(m_ScriptTree.GetParentItem(selected_node),selected_node,NESTED); + CreateDefaultElseClause(m_ScriptTree.GetParentItem(selected_node),selected_node); + m_ScriptTree.Expand(m_ScriptTree.GetParentItem(selected_node),TVE_EXPAND); + } + SetModified(TRUE); +} + + +// Adds a conditional statement node +void CDallasMainDlg::AddConditionalStatementNode(int type, int query_id/*=-1*/) +{ + HTREEITEM selected_node, new_condition_node; + tTreeNodeData *data; + + // Check the ID validity + if(type<0 || type>=MAX_CONDITION_TYPES) return; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Make sure this node is valid for adding a conditional statement + if(data->type==LOGICAL_OPERATOR_NODE) { + tTreeNodeData node_data; + + // Fill in the data appropriately for the new condition node + node_data.type=CONDITIONAL_STATEMENT_NODE; + node_data.ID=type; + + // Add node appropriately with respect to selected node + new_condition_node=AddNodeToTree(selected_node,TVI_LAST,&node_data,TRUE); + + // Create default subnodes for a binary condition + CreateDefaultConditionalStatementSubtree(new_condition_node,type,query_id); + + // Update the new condition node's text to include the expressions + UpdateNodeText(new_condition_node); + SetModified(TRUE); + if(new_condition_node!=NULL) m_ScriptTree.Expand(new_condition_node,TVE_EXPAND); + } +} + + +// Inserts a logical operator node as parent of current node +void CDallasMainDlg::InsertLogicalOperatorNode(int type) +{ + HTREEITEM selected_node, new_logop_node; + tTreeNodeData *data; + + // Check the ID validity + if(type<0 || type>=MAX_LOGICAL_OPERATORS) return; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Make sure this node is valid for inserting a logical operator + if(data->type==LOGICAL_OPERATOR_NODE || data->type==CONDITIONAL_STATEMENT_NODE) { + tTreeNodeData node_data; + + // Fill in the data appropriately for the new condition node + node_data.type=LOGICAL_OPERATOR_NODE; + node_data.ID=type; + + // Add node appropriately with respect to selected node + new_logop_node=AddNodeToTree(m_ScriptTree.GetParentItem(selected_node),selected_node,&node_data,TRUE); + + // Now copy the selected item tree over to the new logop + CopyTree(new_logop_node,TVI_LAST,selected_node); + m_ScriptTree.Expand(new_logop_node,TVE_EXPAND); + + // Add a default ALWAYS so that the logical operator has TWO children + CreateDefaultConditionalStatementNode(new_logop_node); + + // Now delete the selected item tree + m_ScriptTree.SelectItem(new_logop_node); + FreeTreeItem(selected_node); + + SetModified(TRUE); + } +} + + +// Adds a logical operator subtree to the end of selected node's children +void CDallasMainDlg::AddLogicalOperatorNode(int type) +{ + HTREEITEM selected_node, new_logop_node; + tTreeNodeData *data; + + // Check the ID validity + if(type<0 || type>=MAX_LOGICAL_OPERATORS) return; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Make sure this node is valid for inserting a logical operator + if(data->type==LOGICAL_OPERATOR_NODE) { + tTreeNodeData node_data; + + // Fill in the data appropriately for the new condition node + node_data.type=LOGICAL_OPERATOR_NODE; + node_data.ID=type; + + // Add node appropriately with respect to selected node + new_logop_node=AddNodeToTree(selected_node,TVI_LAST,&node_data,TRUE); + + // Add a pair of default ALWAYS's so that the logical operator has TWO children + CreateDefaultConditionalStatementNode(new_logop_node); + CreateDefaultConditionalStatementNode(new_logop_node); + + if(new_logop_node!=NULL) m_ScriptTree.Expand(new_logop_node,TVE_EXPAND); + + SetModified(TRUE); + } +} + + +// Adds an action statement node +void CDallasMainDlg::AddActionStatementNode(int action_ID) +{ + HTREEITEM selected_node, new_action_node; + tTreeNodeData *data; + + // Check the ID validity + if((action_ID<0 || action_ID>=MAX_ACTIONS) && action_ID!=DO_NOTHING_ID) return; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Make sure this node is valid for adding an Action + if(data->type==ACTIONS_HEADER_NODE || data->type==ACTION_STATEMENT_NODE) { + tTreeNodeData node_data; + + // Fill in the data appropriately for the new Action node + node_data.type=ACTION_STATEMENT_NODE; + node_data.ID=action_ID; + + // Add node appropriately with respect to selected node + if(data->type==ACTIONS_HEADER_NODE) + new_action_node=AddNodeToTree(selected_node,TVI_LAST,&node_data,TRUE); + else + new_action_node=AddNodeToTree(m_ScriptTree.GetParentItem(selected_node),selected_node,&node_data,TRUE); + + // If it's a real Action, add in the parameters with appropriate defaults + AddActionParameterNodes(new_action_node); + + // Update the new action node's text to include the parameters + UpdateNodeText(new_action_node); + if(new_action_node!=NULL) m_ScriptTree.Expand(new_action_node,TVE_EXPAND); + + SetModified(TRUE); + } +} + + +// Adds all parameter nodes to the given action node +void CDallasMainDlg::AddActionParameterNodes(HTREEITEM action_node) +{ + CString name_text, default_text, range_text; + tTreeNodeData *data; + char *desc; + + // Make sure node is valid + if(action_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(action_node); + if(data==NULL) return; + + // Make sure it's a valid action + if(data->type!=ACTION_STATEMENT_NODE || data->ID<0 || data->ID>=MAX_ACTIONS) return; + + // Get the action description + desc=GetActionDesc(data->ID); + if(desc==NULL) return; + + // Parse the description, adding default parameter nodes appropriately + while((*desc)!='\0') { + + if((*desc)=='[') { // Note the start of a parameter block + int param_type=ParseParamBlock(desc,name_text,default_text,range_text); + if(param_type>=0 && param_type!=UNKNOWN_PARAMETER_TYPE) + CreateDefaultParameterNode(action_node,TVI_LAST,param_type,name_text.GetBuffer(0),default_text.GetBuffer(0)); + } + else { + desc++; + } + } + SetModified(TRUE); +} + +/* OLD VERSION +// Adds all parameter nodes to the given action node +void CDallasMainDlg::AddActionParameterNodes(HTREEITEM action_node) +{ + tTreeNodeData *data; + char *desc, *desc_copy; + int param_type_char, param_type; + char *param_name; + bool start_block_found; + bool type_delim_found; + int j; + + // Make sure node is valid + if(action_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(action_node); + if(data==NULL) return; + + // Make sure it's a valid action + if(data->type!=ACTION_STATEMENT_NODE || data->ID<0 || data->ID>=MAX_ACTIONS) return; + + // Get the action description + desc=GetActionDesc(data->ID); + if(desc==NULL) return; + + // Make a copy of description (so null chars can be added) + desc_copy=(char *)mem_malloc(strlen(desc)+1); + if(desc_copy==NULL) { + MessageBox("ERROR: Out of memory adding action parameter node!","Out of Memory Error!",MB_OK|MB_ICONEXCLAMATION); + return; + } + strcpy(desc_copy,desc); + + // Parse the description, adding default parameter nodes appropriately + j=0; + start_block_found=FALSE; + type_delim_found=FALSE; + param_name=NULL; + param_type_char=-1; + + while(desc_copy[j]!='\0') { + + if(desc_copy[j]=='[') { // Note the start of a parameter block + start_block_found=TRUE; + } + else if(desc_copy[j]==':' && start_block_found) { // Note the end of parameter type field + type_delim_found=TRUE; + } + else if(desc_copy[j]==']') { // If end of block, add the parameter + + if(param_type_char!=-1 && param_name!=NULL) { + + desc_copy[j]='\0'; // mark the end of the variable name + + // Get the parameter type + param_type=ConvertParamCharToType(param_type_char); + + if(param_type!=UNKNOWN_PARAMETER_TYPE) + CreateDefaultParameterNode(action_node,TVI_LAST,param_type,param_name); + } + + start_block_found=FALSE; + type_delim_found=FALSE; + param_name=NULL; + param_type_char=-1; + } + else if(start_block_found && param_type_char==-1) { + param_type_char=desc_copy[j]; + } + else if(type_delim_found && param_name==NULL) { + param_name=&desc_copy[j]; + } + + j++; + } + + // Free up the copy memory + mem_free(desc_copy); +} +*/ + +// Adds all parameter nodes to the given expression (query) node +void CDallasMainDlg::AddQueryParameterNodes(HTREEITEM query_node) +{ + CString name_text, default_text, range_text; + tTreeNodeData *data; + char *desc; + + // Make sure node is valid + if(query_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(query_node); + if(data==NULL) return; + + // Make sure it's a valid action + if(data->type!=EXPRESSION_NODE || data->ID<0 || data->ID>=MAX_QUERIES) return; + + // Get the action description + desc=GetQueryDesc(data->ID); + if(desc==NULL) return; + + // Parse the description, adding default parameter nodes appropriately + while((*desc)!='\0') { + + if((*desc)=='[') { // Note the start of a parameter block + int param_type=ParseParamBlock(desc,name_text,default_text,range_text); + if(param_type>=0 && param_type!=UNKNOWN_PARAMETER_TYPE) + CreateDefaultParameterNode(query_node,TVI_LAST,param_type,name_text.GetBuffer(0),default_text.GetBuffer(0)); + } + else { + desc++; + } + } + SetModified(TRUE); +} + +/* +// Adds all parameter nodes to the given expression (query) node +void CDallasMainDlg::AddQueryParameterNodes(HTREEITEM query_node) +{ + tTreeNodeData *data; + char *desc, *desc_copy; + int param_type_char, param_type; + char *param_name; + bool start_block_found; + bool type_delim_found; + int j; + + // Make sure node is valid + if(query_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(query_node); + if(data==NULL) return; + + // Make sure it's a valid action + if(data->type!=EXPRESSION_NODE || data->ID<0 || data->ID>=MAX_QUERIES) return; + + // Get the action description + desc=GetQueryDesc(data->ID); + if(desc==NULL) return; + + // Make a copy of description (so null chars can be added) + desc_copy=(char *)mem_malloc(strlen(desc)+1); + if(desc_copy==NULL) { + MessageBox("ERROR: Out of memory adding query parameter node!","Out of Memory Error!",MB_OK|MB_ICONEXCLAMATION); + return; + } + strcpy(desc_copy,desc); + + // Parse the description, adding default parameter nodes appropriately + j=0; + start_block_found=FALSE; + type_delim_found=FALSE; + param_name=NULL; + param_type_char=-1; + + while(desc_copy[j]!='\0') { + + if(desc_copy[j]=='[') { // Note the start of a parameter block + start_block_found=TRUE; + } + else if(desc_copy[j]==':' && start_block_found) { // Note the end of parameter type field + type_delim_found=TRUE; + } + else if(desc_copy[j]==']') { // If end of block, add the parameter + + if(param_type_char!=-1 && param_name!=NULL) { + + desc_copy[j]='\0'; // mark the end of the variable name + + // Get the parameter type + param_type=ConvertParamCharToType(param_type_char); + + if(param_type!=UNKNOWN_PARAMETER_TYPE) + CreateDefaultParameterNode(query_node,TVI_LAST,param_type,param_name); + } + + start_block_found=FALSE; + type_delim_found=FALSE; + param_name=NULL; + param_type_char=-1; + } + else if(start_block_found && param_type_char==-1) { + param_type_char=desc_copy[j]; + } + else if(type_delim_found && param_name==NULL) { + param_name=&desc_copy[j]; + } + + j++; + } + + // Free up the copy memory + mem_free(desc_copy); +} +*/ + +/////////////////////////////////// +// Functions to Replace Tree Nodes +/////////////////////////////////// + + +// Replaces the currently selected node with a new query +void CDallasMainDlg::ReplaceWithQueryNode(int query_ID) +{ + HTREEITEM selected_node, new_query_node; + tTreeNodeData *data; + int query_return_type; + CString query_return_name; + + // Check the ID validity + if(query_ID<0 || query_ID>=MAX_QUERIES) return; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Make sure this node is valid for adding a query + if(data->type==EXPRESSION_NODE || data->type==PARAMETER_NODE) { + tTreeNodeData node_data; + + // Fill in the data appropriately for the new query node + node_data.type=EXPRESSION_NODE; + node_data.ID=query_ID; + + query_return_type=GetQueryReturnType(query_ID,query_return_name); + if(query_return_type==ENUM_PARAMETER_TYPE || query_return_type==FLAG_PARAMETER_TYPE) + strcpy(node_data.name,query_return_name.GetBuffer(0)); + else if(GetNodeType(m_ScriptTree.GetParentItem(selected_node))==CONDITIONAL_STATEMENT_NODE) + strcpy(node_data.name,GetLiteralName(query_return_type)); + else + strcpy(node_data.name,data->name); + + // Add new query node before current node, then delete the current node + new_query_node=AddNodeToTree(m_ScriptTree.GetParentItem(selected_node),selected_node,&node_data,TRUE); + + // Add in the parameters with appropriate defaults + AddQueryParameterNodes(new_query_node); + + // Now delete the selected item tree + m_ScriptTree.SelectItem(new_query_node); + FreeTreeItem(selected_node); + + // Update the new query node's text to include the parameters + UpdateAllParentNodesText(new_query_node); + + // If this node is the first of a comparison conditional, make sure third node's type matches + DoComparisonMatchup(new_query_node); + + if(new_query_node!=NULL) m_ScriptTree.Expand(new_query_node,TVE_EXPAND); + + SetModified(TRUE); + } +} + + +// Replaces the currently selected node with a literal (given a default value) +void CDallasMainDlg::ReplaceWithLiteralNode(int literal_type, int index) +{ + HTREEITEM selected_node, new_literal_node; + tTreeNodeData *data; + + // Check the ID validity + if(literal_type<0 || literal_type>=MAX_LITERALS) return; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Make sure this node is valid for adding a query + if(data->type==EXPRESSION_NODE || data->type==PARAMETER_NODE) { + + CString tmp_str; + if(literal_type==ENUM_PARAMETER_TYPE) + tmp_str=m_EnumDatabase[index].name; + else if(literal_type==FLAG_PARAMETER_TYPE) + tmp_str=m_FlagDatabase[index].name; + else if(GetNodeType(m_ScriptTree.GetParentItem(selected_node))==CONDITIONAL_STATEMENT_NODE) + tmp_str=GetLiteralName(literal_type); + else + tmp_str=data->name; + + // Create a default parameter node for the chosen literal + CString name_text, default_text, range_text; + int n, param_type; + n=GetChildPosition(selected_node); + param_type=ParseNthParam(m_ScriptTree.GetParentItem(selected_node),n,name_text,default_text,range_text); + if(param_type>=0) + new_literal_node=CreateDefaultParameterNode(m_ScriptTree.GetParentItem(selected_node),selected_node,literal_type,tmp_str.GetBuffer(0),default_text.GetBuffer(0)); + else + new_literal_node=CreateDefaultParameterNode(m_ScriptTree.GetParentItem(selected_node),selected_node,literal_type,tmp_str.GetBuffer(0)); + + // Now delete the selected item tree + m_ScriptTree.SelectItem(new_literal_node); + FreeTreeItem(selected_node); + + // Update the new literal nodes text + UpdateAllParentNodesText(new_literal_node); + + // If this node is the first of a comparison conditional, make sure third node's type matches + DoComparisonMatchup(new_literal_node); + + SetModified(TRUE); + } +} + + +// If this node is the first of a comparison conditional, make sure third node's type matches +// If they don't match, remove the third node and replace it with a default param that does match +void CDallasMainDlg::DoComparisonMatchup(HTREEITEM node) +{ + int node_type, onode_type; + CString node_name, onode_name; + HTREEITEM other_node, new_param_node; + + if(node==NULL) return; + + // If it's not the first node of a comparison conditional, nothing need be done + if(!ParentIsComparisonConditional(node) || GetChildPosition(node)!=1) return; + + // ok, it is, so now we need to get the other node being compared + other_node=GetNthChild(m_ScriptTree.GetParentItem(node),3); + if(other_node==NULL) return; + + // Get the other node's data + onode_type=GetParamType(other_node,onode_name); + + // Get this node's data + node_type=GetParamType(node,node_name); + if(node_type<0) return; + + // Do the node types match? If they do, get out of here + if(node_type==onode_type) { + if(node_type==ENUM_PARAMETER_TYPE || node_type==FLAG_PARAMETER_TYPE) { + if(node_name.IsEmpty()) + return; + else if(strcmp(node_name.GetBuffer(0),onode_name.GetBuffer(0))==0) + return; + } + else + return; + } + + // If we're here, then the nodes don't match... so create a matching default param + CString tmp_str; + if(node_type==ENUM_PARAMETER_TYPE || node_type==FLAG_PARAMETER_TYPE) + tmp_str=node_name; + else + tmp_str=GetLiteralName(node_type); + + new_param_node=CreateDefaultParameterNode(m_ScriptTree.GetParentItem(other_node),other_node,node_type,tmp_str.GetBuffer(0)); + + // Now delete the old param node + FreeTreeItem(other_node); + + // Update the new literal nodes text + UpdateAllParentNodesText(new_param_node); + + SetModified(TRUE); +} + + +// Replaces the currently selected node with a new action +void CDallasMainDlg::ReplaceWithActionNode(int action_ID) +{ + HTREEITEM selected_node, new_action_node; + tTreeNodeData *data; + + // Check the ID validity + if((action_ID<0 || action_ID>=MAX_ACTIONS) && action_ID!=DO_NOTHING_ID) return; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Make sure this node is valid for adding an Action + if(data->type==ACTION_STATEMENT_NODE) { + tTreeNodeData node_data; + + // Fill in the data appropriately for the new Action node + node_data.type=ACTION_STATEMENT_NODE; + node_data.ID=action_ID; + + // Add node appropriately with respect to selected node + new_action_node=AddNodeToTree(m_ScriptTree.GetParentItem(selected_node),selected_node,&node_data,TRUE); + + // If it's a real Action, add in the parameters with appropriate defaults + AddActionParameterNodes(new_action_node); + + // Now delete the selected item tree + m_ScriptTree.SelectItem(new_action_node); + FreeTreeItem(selected_node); + + // Update the new action node's text to include the parameters + UpdateNodeText(new_action_node); + if(new_action_node!=NULL) m_ScriptTree.Expand(new_action_node,TVE_EXPAND); + SetModified(TRUE); + } +} + + +// Replaces the currently selected node with a new logical operation +void CDallasMainDlg::ReplaceWithLogOpNode(int type) +{ + HTREEITEM selected_node, new_logop_node; + tTreeNodeData *data; + + // Check the ID validity + if(type<0 || type>=MAX_LOGICAL_OPERATORS) return; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // If this node IS a logical operator, just change its data + if(data->type==LOGICAL_OPERATOR_NODE) { + data->ID=type; + UpdateAllParentNodesText(selected_node); + SetModified(TRUE); + return; + } + + // Make sure this node is valid for inserting a logical operator + if(data->type==LOGICAL_OPERATOR_NODE || data->type==CONDITIONAL_STATEMENT_NODE) { + tTreeNodeData node_data; + + // Fill in the data appropriately for the new condition node + node_data.type=LOGICAL_OPERATOR_NODE; + node_data.ID=type; + + // Add node appropriately with respect to selected node + new_logop_node=AddNodeToTree(m_ScriptTree.GetParentItem(selected_node),selected_node,&node_data,TRUE); + + // Add a pair of default ALWAYS's so that the logical operator has TWO children + CreateDefaultConditionalStatementNode(new_logop_node); + CreateDefaultConditionalStatementNode(new_logop_node); + + // Now delete the selected item tree + m_ScriptTree.SelectItem(new_logop_node); + FreeTreeItem(selected_node); + + if(new_logop_node!=NULL) m_ScriptTree.Expand(new_logop_node,TVE_EXPAND); + SetModified(TRUE); + } +} + + +// Replaces the currently selected node with a new condition +void CDallasMainDlg::ReplaceWithConditionNode(int type, int query_id/*=-1*/) +{ + HTREEITEM selected_node, new_condition_node; + tTreeNodeData *data; + + // Check the ID validity + if(type<0 || type>=MAX_CONDITION_TYPES) return; + + // Obtain the currently selected node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Get the node's data + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + // Make sure this node is valid for adding a conditional statement + if(data->type==LOGICAL_OPERATOR_NODE || data->type==CONDITIONAL_STATEMENT_NODE) { + tTreeNodeData node_data; + + // Fill in the data appropriately for the new condition node + node_data.type=CONDITIONAL_STATEMENT_NODE; + node_data.ID=type; + + // Add node appropriately with respect to selected node + new_condition_node=AddNodeToTree(m_ScriptTree.GetParentItem(selected_node),selected_node,&node_data,TRUE); + + // Create default subnodes for a binary condition + CreateDefaultConditionalStatementSubtree(new_condition_node,type,query_id); + + // Now delete the selected item tree + m_ScriptTree.SelectItem(new_condition_node); + FreeTreeItem(selected_node); + + // Update the new condition node's text to include the expressions + UpdateNodeText(new_condition_node); + + if(new_condition_node!=NULL) m_ScriptTree.Expand(new_condition_node,TVE_EXPAND); + SetModified(TRUE); + } +} + + +///////////////////////////////////////////////////////////////////////////// +// Functions to Create (and Add) default Tree Nodes +///////////////////////////////////////////////////////////////////////////// + + +// Inserts a default script tree before the specified node (or at the end if NULL) +HTREEITEM CDallasMainDlg::CreateDefaultScriptTree(int script_ID, HTREEITEM insert_before/*=NULL*/) +{ + HTREEITEM ib_node, parent; + tTreeNodeData node_data; + + ib_node=GetParentNodeOfType(insert_before,SCRIPT_HEADER_NODE); + if(ib_node!=NULL && m_ScriptTree.GetParentItem(ib_node)!=NULL) + ib_node=m_ClipboardNode; + if(ib_node==NULL) { + if(m_ClipboardNode!=NULL) + ib_node=m_ClipboardNode; + else + ib_node=TVI_LAST; + } + + + // Create the default Script Header node + node_data.type=SCRIPT_HEADER_NODE; + node_data.ID=script_ID; + strcpy(node_data.name,DEFAULT_SCRIPT_HEADER_STRING); + parent=AddNodeToTree(TVI_ROOT,ib_node,&node_data); + + // Create the default Script owner node + node_data.type=SCRIPT_OWNER_NODE; + node_data.ID=NOT_SPECIFIED_TYPE; + node_data.int_val=0; + AddNodeToTree(parent,TVI_LAST,&node_data); + + // Create the default Event Type Node + node_data.type=SCRIPT_EVENT_NODE; + node_data.ID=COLLIDE_EVENT_TYPE; + AddNodeToTree(parent,TVI_LAST,&node_data); + + CreateDefaultIfThenClause(parent,TVI_LAST,TOP_LEVEL); + + if(parent!=NULL) m_ScriptTree.Expand(parent,TVE_EXPAND); + SetModified(TRUE); + + return(parent); +} + + +// Create default IF-THEN Clause +HTREEITEM CDallasMainDlg::CreateDefaultIfThenClause(HTREEITEM parent, HTREEITEM insert_before, int type) +{ + HTREEITEM header; + tTreeNodeData node_data; + + if(parent==NULL || insert_before==NULL) return NULL; + + // Create the default Conditional header Node + node_data.type=CONDITIONAL_HEADER_NODE; + node_data.ID=type; + header=AddNodeToTree(parent,insert_before,&node_data); + if(header==NULL) return(NULL); + + // Create the default conditional statement Node + CreateDefaultConditionalStatementNode(header); + if(header!=NULL) m_ScriptTree.Expand(header,TVE_EXPAND); + + + // Create the default Action header Node + node_data.type=ACTIONS_HEADER_NODE; + node_data.ID=type; + if(type==TOP_LEVEL) { + node_data.subID=0; + node_data.int_val=CONTINUE_SCRIPT_CHAIN; + } + else { + node_data.subID=THEN_CLAUSE; + node_data.int_val=0; + } + header=AddNodeToTree(parent,insert_before,&node_data); + + // Create the default action statement Node + CreateDefaultActionStatementNode(header); + if(header!=NULL) m_ScriptTree.Expand(header,TVE_EXPAND); + SetModified(TRUE); + + return(header); +} + + +// Create default IF-THEN Clause +HTREEITEM CDallasMainDlg::CreateDefaultElseClause(HTREEITEM parent, HTREEITEM insert_before) +{ + HTREEITEM header; + tTreeNodeData node_data; + + if(parent==NULL || insert_before==NULL) return NULL; + + // Create the default Action header Node + node_data.type=ACTIONS_HEADER_NODE; + node_data.ID=NESTED; + node_data.subID=ELSE_CLAUSE; + node_data.int_val=0; + header=AddNodeToTree(parent,insert_before,&node_data); + + // Create the default action statement Node + CreateDefaultActionStatementNode(header); + if(header!=NULL) m_ScriptTree.Expand(header,TVE_EXPAND); + SetModified(TRUE); + + return(header); +} + + +// Create default conditional statement node +HTREEITEM CDallasMainDlg::CreateDefaultConditionalStatementNode(HTREEITEM parent) +{ + tTreeNodeData node_data; + + if(parent==NULL) return NULL; + + node_data.type=CONDITIONAL_STATEMENT_NODE; + node_data.ID=ALWAYS_STATEMENT; + SetModified(TRUE); + + return(AddNodeToTree(parent,TVI_LAST,&node_data)); +} + + +// Create default conditional statement node +HTREEITEM CDallasMainDlg::CreateDefaultConditionalStatementSubtree(HTREEITEM parent, int type, int query_id/*=-1*/) +{ + HTREEITEM last_added_node, first_parm_node; + + if(parent==NULL) return NULL; + if(type==ALWAYS_STATEMENT) return NULL; + + // Add default binary subtree + if(type==BINARY_STATEMENT) { + first_parm_node=CreateDefaultParameterNode(parent,TVI_LAST,BOOL_PARAMETER_TYPE,"Literal"); + last_added_node=CreateDefaultExpressionOperatorNode(parent,BINARY_OPERATOR_TYPE); + } + + // Add default comparison subtree + if(type==COMPARISON_STATEMENT) { + first_parm_node=CreateDefaultParameterNode(parent,TVI_LAST,FLOAT_PARAMETER_TYPE,"Literal"); + last_added_node=CreateDefaultExpressionOperatorNode(parent,COMPARISON_OPERATOR_TYPE); + last_added_node=CreateDefaultParameterNode(parent,TVI_LAST,FLOAT_PARAMETER_TYPE,"Literal"); + } + + // Replace first node with a query if necessary + if(first_parm_node!=NULL && query_id>=0 && query_idtype==EXPRESSION_NODE || data->type==PARAMETER_NODE)) { + tTreeNodeData node_data; + int query_return_type; + HTREEITEM new_query_node; + CString query_return_name; + + // Fill in the data appropriately for the new query node + node_data.type=EXPRESSION_NODE; + node_data.ID=query_id; + + query_return_type=GetQueryReturnType(query_id,query_return_name); + if(query_return_type==ENUM_PARAMETER_TYPE || query_return_type==FLAG_PARAMETER_TYPE) + strcpy(node_data.name,query_return_name.GetBuffer(0)); + else if(GetNodeType(m_ScriptTree.GetParentItem(first_parm_node))==CONDITIONAL_STATEMENT_NODE) + strcpy(node_data.name,GetLiteralName(query_return_type)); + else + strcpy(node_data.name,data->name); + + // Add new query node before current node, then delete the current node + new_query_node=AddNodeToTree(m_ScriptTree.GetParentItem(first_parm_node),first_parm_node,&node_data,TRUE); + + // Add in the parameters with appropriate defaults + AddQueryParameterNodes(new_query_node); + + // Now delete the selected item tree + FreeTreeItem(first_parm_node); + + // Update the new query node's text to include the parameters + UpdateAllParentNodesText(new_query_node); + + // If this node is the first of a comparison conditional, make sure third node's type matches + DoComparisonMatchup(new_query_node); + + if(new_query_node!=NULL) m_ScriptTree.Expand(new_query_node,TVE_EXPAND); + } + } + + SetModified(TRUE); + + return(last_added_node); +} + + +// Create default expression operator node +HTREEITEM CDallasMainDlg::CreateDefaultExpressionOperatorNode(HTREEITEM parent, int type) +{ + tTreeNodeData node_data; + + if(parent==NULL) return NULL; + if(type!=BINARY_OPERATOR_TYPE && type!=COMPARISON_OPERATOR_TYPE) return NULL; + + node_data.type=EXPRESSION_OPERATOR_NODE; + node_data.ID=type; + + if(type==BINARY_OPERATOR_TYPE) + node_data.subID=IS_TRUE; + else + node_data.subID=EQUAL_TO; + + SetModified(TRUE); + + return(AddNodeToTree(parent,TVI_LAST,&node_data)); +} + + +// Create default action statement node +HTREEITEM CDallasMainDlg::CreateDefaultActionStatementNode(HTREEITEM parent) +{ + tTreeNodeData node_data; + + if(parent==NULL) return NULL; + + node_data.type=ACTION_STATEMENT_NODE; + node_data.ID=DO_NOTHING_ID; + + SetModified(TRUE); + + return(AddNodeToTree(parent,TVI_LAST,&node_data)); +} + +// Create default parameter node, and assigns it an appropriate default value +// based upon the parameter type +HTREEITEM CDallasMainDlg::CreateDefaultParameterNode(HTREEITEM parent, HTREEITEM insert_before, int param_type, char *name, char *def_value/*=NULL*/) +{ + tTreeNodeData node_data; + + if(parent==NULL || insert_before==NULL || name==NULL) return NULL; + + node_data.type=PARAMETER_NODE; + node_data.ID=param_type; + strcpy(node_data.name,name); + + // Store default values + switch(param_type) { + case DOOR_PARAMETER_TYPE: + node_data.int_val=OBJECT_HANDLE_NONE; + node_data.subID=USE_OBJECT_HANDLE; + strcpy(node_data.str_val,""); + break; + case OBJECT_PARAMETER_TYPE: + if(def_value!=NULL && strlen(def_value)!=0) { + if(strcmp(def_value,"ME")==0) { + node_data.int_val=OBJECT_HANDLE_NONE; + node_data.subID=USE_ME_HANDLE; + strcpy(node_data.str_val,""); + break; + } + if(strcmp(def_value,"IT")==0) { + node_data.int_val=OBJECT_HANDLE_NONE; + node_data.subID=USE_IT_HANDLE; + strcpy(node_data.str_val,""); + break; + } + } + node_data.int_val=OBJECT_HANDLE_NONE; + node_data.subID=USE_OBJECT_HANDLE; + strcpy(node_data.str_val,""); + break; + case ROOM_PARAMETER_TYPE: + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + break; + case TRIGGER_PARAMETER_TYPE: + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + break; + case INT_PARAMETER_TYPE: + if(def_value==NULL || strlen(def_value)==0) + node_data.int_val=0; + else + node_data.int_val=atoi(def_value); + break; + case BOOL_PARAMETER_TYPE: + if(def_value==NULL || strlen(def_value)==0) + node_data.int_val=TRUE; + else { + if(stricmp(def_value,"false")==0) + node_data.int_val=FALSE; + else + node_data.int_val=TRUE; + } + break; + case FLOAT_PARAMETER_TYPE: + if(def_value==NULL || strlen(def_value)==0) + node_data.float_val1=0.0; + else + node_data.float_val1=atof(def_value); + break; + case VECTOR_PARAMETER_TYPE: + node_data.float_val1=0.0; + node_data.float_val2=0.0; + node_data.float_val3=0.0; + break; + case STRING_PARAMETER_TYPE: + strcpy(node_data.str_val,""); + break; + case PERCENTAGE_PARAMETER_TYPE: + if(def_value==NULL || strlen(def_value)==0) + node_data.float_val1=0.0; + else + node_data.float_val1=atof(def_value); + break; + case ENUM_PARAMETER_TYPE: + { + if(def_value!=NULL && strlen(def_value)>0) { + if(GetEnumValue(name,def_value,node_data.int_val)) { + node_data.subID=USE_ENUM_VALUE; + break; + } + } + + int DBslot; + DBslot=GetEnumID(name); + node_data.subID=USE_ENUM_VALUE; + if(DBslot!=INVALID_ENUM && m_EnumDatabase[DBslot].num_values>0) + node_data.int_val=m_EnumDatabase[DBslot].values[0].value; + else + node_data.int_val=0; + } + break; + case SCRIPT_PARAMETER_TYPE: + node_data.int_val=GetScriptID(parent); + if(node_data.int_val<0) + node_data.int_val=0; + break; + case SOUND_PARAMETER_TYPE: + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + break; + case SPECNAME_PARAMETER_TYPE: + strcpy(node_data.str_val,""); + break; + case TEXTURE_PARAMETER_TYPE: + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + break; + case FLAG_PARAMETER_TYPE: + if(def_value==NULL || strlen(def_value)==0) + node_data.int_val=0; + else + node_data.int_val=atoi(def_value); + break; + case PATH_PARAMETER_TYPE: + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + break; + case MATCEN_PARAMETER_TYPE: + node_data.subID=USE_MATCEN_VALUE; + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + break; + case LEVEL_GOAL_PARAMETER_TYPE: + node_data.subID=USE_LEVEL_GOAL_VALUE; + node_data.int_val=NOT_SPECIFIED_TYPE; + strcpy(node_data.str_val,""); + break; + case STRM_AUDIO_PARAMETER_TYPE: + strcpy(node_data.str_val,""); + break; + default: + break; + } + + SetModified(TRUE); + + return(AddNodeToTree(parent,insert_before,&node_data)); +} + + +// Creates the clipboard node and puts it into the tree +HTREEITEM CDallasMainDlg::CreateDefaultClipboardNode(void) +{ + tTreeNodeData node_data; + + if(m_ClipboardNode!=NULL) { + FreeTreeItem(m_ClipboardNode); + m_ClipboardNode=NULL; + } + + node_data.type=CLIPBOARD_HEADER_NODE; + SetModified(TRUE); + + m_ClipboardNode=AddNodeToTree(TVI_ROOT,TVI_LAST,&node_data); + return(m_ClipboardNode); +} + + +/////////////////////////////////// +// Functions to Handle Copy/Paste +/////////////////////////////////// + + +// Copies the selected script into the clipboard +void CDallasMainDlg::PerformScriptCopy(void) +{ + HTREEITEM selected_node; + HTREEITEM script_header_node; + HTREEITEM new_script_node; + + // Make sure we have a clipboard + if(m_ClipboardNode==NULL) return; + + // Get the selected tree node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // If it's a conditional statement node, let it be the header + if(GetNodeType(selected_node)==CONDITIONAL_STATEMENT_NODE) { + PerformConditionalCopy(selected_node); + return; + } + + // If it's a logical operator node, let it be the header + if(GetNodeType(selected_node)==LOGICAL_OPERATOR_NODE) { + PerformLogOpCopy(selected_node); + return; + } + + // If it's an action node, let it be the header + if(GetNodeType(selected_node)==ACTION_STATEMENT_NODE) { + PerformActionCopy(selected_node); + return; + } + + // If it's a nested IF clause, let it be the header + if(NodeIsIfClause(selected_node)) { + PerformClauseCopy(selected_node); + return; + } + + // If it's not a script header node, then it can't be copied + if(GetNodeType(selected_node)!=SCRIPT_HEADER_NODE) { + MessageBox("Copy/Paste is not supported for the currently selected script item.","Invalid Copy/Paste",MB_OK); + return; + } + + // Get the script header node + script_header_node=GetParentNodeOfType(selected_node,SCRIPT_HEADER_NODE); + if(script_header_node==NULL) return; + + // If the script header has a parent, then it must be a clipboard node + if(m_ScriptTree.GetParentItem(script_header_node)!=NULL) return; + + // If the clipboard, has a script already, kill the old one + FreeTreeItemChildren(m_ClipboardNode); + + // Now copy the script over to the clipboard + new_script_node=CopyTree(m_ClipboardNode,TVI_LAST,script_header_node); + if(new_script_node!=NULL) { + UpdateAllParentNodesText(new_script_node); + m_ScriptTree.Expand(m_ClipboardNode,TVE_COLLAPSE); + } +} + + +// Copies the selected script action into the clipboard +void CDallasMainDlg::PerformActionCopy(HTREEITEM action_node) +{ + HTREEITEM script_header_node; + HTREEITEM new_script_node; + + // Make sure we have a clipboard + if(m_ClipboardNode==NULL) return; + + // Get the selected tree node + if(action_node==NULL) return; + + // If it's an action node, let it be the header + if(GetNodeType(action_node)!=ACTION_STATEMENT_NODE) return; + + // Get the script header node + script_header_node=GetParentNodeOfType(action_node,SCRIPT_HEADER_NODE); + if(script_header_node==NULL) return; + + // If the script header has a parent, then it must be a clipboard node + if(m_ScriptTree.GetParentItem(script_header_node)!=NULL) return; + + // If the clipboard, has a script already, kill the old one + FreeTreeItemChildren(m_ClipboardNode); + + // Now copy the action over to the clipboard + new_script_node=CopyTree(m_ClipboardNode,TVI_LAST,action_node); + if(new_script_node!=NULL) { + UpdateAllParentNodesText(new_script_node); + m_ScriptTree.Expand(m_ClipboardNode,TVE_COLLAPSE); + } +} + + +// Copies the selected script conditional statement into the clipboard +void CDallasMainDlg::PerformConditionalCopy(HTREEITEM conditional_node) +{ + HTREEITEM script_header_node; + HTREEITEM new_script_node; + + // Make sure we have a clipboard + if(m_ClipboardNode==NULL) return; + + // Get the selected tree node + if(conditional_node==NULL) return; + + // If it's an action node, let it be the header + if(GetNodeType(conditional_node)!=CONDITIONAL_STATEMENT_NODE) return; + + // Get the script header node + script_header_node=GetParentNodeOfType(conditional_node,SCRIPT_HEADER_NODE); + if(script_header_node==NULL) return; + + // If the script header has a parent, then it must be a clipboard node + if(m_ScriptTree.GetParentItem(script_header_node)!=NULL) return; + + // If the clipboard, has a script already, kill the old one + FreeTreeItemChildren(m_ClipboardNode); + + // Now copy the conditional statement over to the clipboard + new_script_node=CopyTree(m_ClipboardNode,TVI_LAST,conditional_node); + if(new_script_node!=NULL) { + UpdateAllParentNodesText(new_script_node); + m_ScriptTree.Expand(m_ClipboardNode,TVE_COLLAPSE); + } +} + + +// Copies the selected script logical operator into the clipboard +void CDallasMainDlg::PerformLogOpCopy(HTREEITEM logop_node) +{ + HTREEITEM script_header_node; + HTREEITEM new_script_node; + + // Make sure we have a clipboard + if(m_ClipboardNode==NULL) return; + + // Get the selected tree node + if(logop_node==NULL) return; + + // If it's a logop node, let it be the header + if(GetNodeType(logop_node)!=LOGICAL_OPERATOR_NODE) return; + + // Get the script header node + script_header_node=GetParentNodeOfType(logop_node,SCRIPT_HEADER_NODE); + if(script_header_node==NULL) return; + + // If the script header has a parent, then it must be a clipboard node + if(m_ScriptTree.GetParentItem(script_header_node)!=NULL) return; + + // If the clipboard, has a script already, kill the old one + FreeTreeItemChildren(m_ClipboardNode); + + // Now copy the logical operator over to the clipboard + new_script_node=CopyTree(m_ClipboardNode,TVI_LAST,logop_node); + if(new_script_node!=NULL) { + UpdateAllParentNodesText(new_script_node); + m_ScriptTree.Expand(m_ClipboardNode,TVE_COLLAPSE); + } +} + + +// Copies the selected script if-then-else clause into the clipboard +void CDallasMainDlg::PerformClauseCopy(HTREEITEM clause_node) +{ + HTREEITEM script_header_node; + HTREEITEM new_script_node; + HTREEITEM if_node, then_node, else_node; + + // Make sure we have a clipboard + if(m_ClipboardNode==NULL) return; + + // Get the selected tree node + if(clause_node==NULL) return; + + // Make sure it's an IF header + if(!NodeIsIfClause(clause_node)) + return; + + // Get the script header node + script_header_node=GetParentNodeOfType(clause_node,SCRIPT_HEADER_NODE); + if(script_header_node==NULL) return; + + // If the script header has a parent, then it must be a clipboard node + if(m_ScriptTree.GetParentItem(script_header_node)!=NULL) return; + + // Get the then clause node + if_node=clause_node; + then_node=m_ScriptTree.GetNextSiblingItem(if_node); + if(!NodeIsClauseOfType(then_node,THEN_CLAUSE)) return; + + // Get the else clause node + else_node=m_ScriptTree.GetNextSiblingItem(then_node); + if(!NodeIsClauseOfType(else_node,ELSE_CLAUSE)) else_node=NULL; + + // If the clipboard, has a script already, kill the old one + FreeTreeItemChildren(m_ClipboardNode); + + // Now copy the IF clause over to the clipboard + new_script_node=CopyTree(m_ClipboardNode,TVI_LAST,if_node); + if(new_script_node!=NULL) { + UpdateAllParentNodesText(new_script_node); + m_ScriptTree.Expand(m_ClipboardNode,TVE_COLLAPSE); + } + + // Now copy the THEN clause over to the clipboard + new_script_node=CopyTree(m_ClipboardNode,TVI_LAST,then_node); + if(new_script_node!=NULL) { + UpdateAllParentNodesText(new_script_node); + m_ScriptTree.Expand(m_ClipboardNode,TVE_COLLAPSE); + } + + // Now copy the ELSE clause over (if one exists) + if(else_node!=NULL) { + new_script_node=CopyTree(m_ClipboardNode,TVI_LAST,else_node); + if(new_script_node!=NULL) { + UpdateAllParentNodesText(new_script_node); + m_ScriptTree.Expand(m_ClipboardNode,TVE_COLLAPSE); + } + } +} + + +// Inserts the clipboard script before the selected script (or clipboard) +void CDallasMainDlg::PerformScriptPaste(void) +{ + HTREEITEM selected_node; + HTREEITEM src_script_header_node; + HTREEITEM dest_insert_before; + HTREEITEM new_script_header; + + // Make sure we have a clipboard + if(m_ClipboardNode==NULL) return; + + // Get the clipboard child script + src_script_header_node=m_ScriptTree.GetChildItem(m_ClipboardNode); + if(src_script_header_node==NULL) return; + + // See if the clipboard has a conditional statement + if(GetNodeType(src_script_header_node)==CONDITIONAL_STATEMENT_NODE) { + PerformConditionalPaste(src_script_header_node); + return; + } + + // See if the clipboard has a logical operator + if(GetNodeType(src_script_header_node)==LOGICAL_OPERATOR_NODE) { + PerformLogOpPaste(src_script_header_node); + return; + } + + // See if the clipboard has an action + if(GetNodeType(src_script_header_node)==ACTION_STATEMENT_NODE) { + PerformActionPaste(src_script_header_node); + return; + } + + // See if the clipboard has an IF clause + if(NodeIsIfClause(src_script_header_node)) { + PerformClausePaste(src_script_header_node); + return; + } + + // If the clipboard doesn't have a script header, get outta here + if(GetNodeType(src_script_header_node)!=SCRIPT_HEADER_NODE) return; + + // Get the selected tree node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + if(selected_node==m_ClipboardNode) + dest_insert_before=m_ClipboardNode; + else { + dest_insert_before=GetParentNodeOfType(selected_node,SCRIPT_HEADER_NODE); + if(dest_insert_before==NULL) return; + + // If the script header has a parent, then it must be a clipboard node + if(m_ScriptTree.GetParentItem(dest_insert_before)!=NULL) dest_insert_before=m_ClipboardNode; + } + + // Now copy the script over to the clipboard + new_script_header=CopyTree(TVI_ROOT,dest_insert_before,src_script_header_node); + if(new_script_header==NULL) return; + + // Change the script ID for the new node + tTreeNodeData *data=(tTreeNodeData *)m_ScriptTree.GetItemData(new_script_header); + if(data==NULL) return; + + int new_id=GetLowestUnusedScriptID(); + data->ID=new_id; + UpdateNodeText(new_script_header); + HighlightScript(new_script_header); + + if(new_id==m_NextScriptID) m_NextScriptID++; + + m_ScriptTree.SelectItem(new_script_header); + AssignSpecificValue(); + SetModified(TRUE); +} + + +// Inserts the clipboard action before the selected node (or to end of children) +void CDallasMainDlg::PerformActionPaste(HTREEITEM src_action_node) +{ + HTREEITEM selected_node; + HTREEITEM new_action_node; + tTreeNodeData *data; + + // Make sure we have a clipboard + if(m_ClipboardNode==NULL) return; + + // See if the clipboard has an action + if(GetNodeType(src_action_node)!=ACTION_STATEMENT_NODE) return; + + // Get the selected tree node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Make sure it's not the same node! + if(selected_node==src_action_node) return; + + // Make sure it's not in the clipboard + if(NodeIsInClipboard(selected_node)) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + if(data->type==ACTION_STATEMENT_NODE || (data->type==CONDITIONAL_HEADER_NODE && data->ID==NESTED)) + new_action_node=CopyTree(m_ScriptTree.GetParentItem(selected_node),selected_node,src_action_node); + else if(data->type==ACTIONS_HEADER_NODE) { + new_action_node=CopyTree(selected_node,TVI_LAST,src_action_node); + } + else { + return; + } + + // Now copy the script over to the clipboard + if(new_action_node==NULL) return; + + UpdateAllParentNodesText(new_action_node); + SetModified(TRUE); +} + + +// Replaces selected node with the clipboard conditional statement +void CDallasMainDlg::PerformConditionalPaste(HTREEITEM src_conditional_node) +{ + HTREEITEM selected_node; + HTREEITEM new_conditional_node; + HTREEITEM parent; + tTreeNodeData *data; + + // Make sure we have a clipboard + if(m_ClipboardNode==NULL) return; + + // See if the clipboard has a conditional statement + if(GetNodeType(src_conditional_node)!=CONDITIONAL_STATEMENT_NODE) return; + + // Get the selected tree node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Make sure it's not the same node! + if(selected_node==src_conditional_node) return; + + // Make sure it's not in the clipboard + if(NodeIsInClipboard(selected_node)) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + if(data->type==CONDITIONAL_STATEMENT_NODE || data->type==LOGICAL_OPERATOR_NODE) { + new_conditional_node=CopyTree(m_ScriptTree.GetParentItem(selected_node),selected_node,src_conditional_node); + m_ScriptTree.SelectItem(new_conditional_node); + + // Delete the old conditional + parent=m_ScriptTree.GetParentItem(selected_node); + FreeTreeItem(selected_node); + + ConfirmAfterDelete(parent); + SetModified(TRUE); + } + else { + return; + } + + // Now copy the script over to the clipboard + if(new_conditional_node==NULL) return; + + UpdateAllParentNodesText(new_conditional_node); +} + + +// Replaces selected node with the clipboard logical operator node +void CDallasMainDlg::PerformLogOpPaste(HTREEITEM src_logop_node) +{ + HTREEITEM selected_node; + HTREEITEM new_logop_node; + HTREEITEM parent; + tTreeNodeData *data; + + // Make sure we have a clipboard + if(m_ClipboardNode==NULL) return; + + // See if the clipboard has a logical operator + if(GetNodeType(src_logop_node)!=LOGICAL_OPERATOR_NODE) return; + + // Get the selected tree node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Make sure it's not the same node! + if(selected_node==src_logop_node) return; + + // Make sure it's not in the clipboard + if(NodeIsInClipboard(selected_node)) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + if(data->type==CONDITIONAL_STATEMENT_NODE || data->type==LOGICAL_OPERATOR_NODE) { + new_logop_node=CopyTree(m_ScriptTree.GetParentItem(selected_node),selected_node,src_logop_node); + m_ScriptTree.SelectItem(new_logop_node); + + // Delete the old conditional + parent=m_ScriptTree.GetParentItem(selected_node); + FreeTreeItem(selected_node); + + ConfirmAfterDelete(parent); + SetModified(TRUE); + } + else { + return; + } + + // Now copy the script over to the clipboard + if(new_logop_node==NULL) return; + + UpdateAllParentNodesText(new_logop_node); +} + + +// Inserts the clipboard action before the selected node (or to end of children) +void CDallasMainDlg::PerformClausePaste(HTREEITEM src_clause_node) +{ + HTREEITEM selected_node; + HTREEITEM new_clause_node; + HTREEITEM if_node, then_node, else_node; + tTreeNodeData *data; + + // Make sure we have a clipboard + if(m_ClipboardNode==NULL) return; + + // See if the clipboard has an IF clause + if(!NodeIsIfClause(src_clause_node)) return; + + // Get the then clause node + if_node=src_clause_node; + then_node=m_ScriptTree.GetNextSiblingItem(if_node); + if(!NodeIsClauseOfType(then_node,THEN_CLAUSE)) return; + + // Get the else clause node + else_node=m_ScriptTree.GetNextSiblingItem(then_node); + if(!NodeIsClauseOfType(else_node,ELSE_CLAUSE)) else_node=NULL; + + // Get the selected tree node + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + + // Make sure it's not the same node! + if(selected_node==src_clause_node) return; + + // Make sure it's not in the clipboard + if(NodeIsInClipboard(selected_node)) return; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); + if(data==NULL) return; + + if(data->type==ACTION_STATEMENT_NODE || (data->type==CONDITIONAL_HEADER_NODE && data->ID==NESTED)) { + // Copy over IF clause + new_clause_node=CopyTree(m_ScriptTree.GetParentItem(selected_node),selected_node,if_node); + UpdateAllParentNodesText(new_clause_node); + + // Copy over THEN clause + new_clause_node=CopyTree(m_ScriptTree.GetParentItem(selected_node),selected_node,then_node); + UpdateAllParentNodesText(new_clause_node); + + // Copy over ELSE clause (if one exists) + if(else_node!=NULL) { + new_clause_node=CopyTree(m_ScriptTree.GetParentItem(selected_node),selected_node,else_node); + UpdateAllParentNodesText(new_clause_node); + } + } + else if(data->type==ACTIONS_HEADER_NODE) { + // Copy over IF clause + new_clause_node=CopyTree(selected_node,TVI_LAST,if_node); + UpdateAllParentNodesText(new_clause_node); + + // Copy over THEN clause + new_clause_node=CopyTree(selected_node,TVI_LAST,then_node); + UpdateAllParentNodesText(new_clause_node); + + // Copy over ELSE clause (if one exists) + if(else_node!=NULL) { + new_clause_node=CopyTree(selected_node,TVI_LAST,else_node); + UpdateAllParentNodesText(new_clause_node); + } + } + else { + return; + } + + // Now copy the script over to the clipboard + if(new_clause_node==NULL) return; + + SetModified(TRUE); +} + + +// Checks to see if the given node is a child of the clipboard header +bool CDallasMainDlg::NodeIsInClipboard(HTREEITEM node) +{ + HTREEITEM parent; + + parent=GetParentNodeOfType(node,CLIPBOARD_HEADER_NODE); + + if(parent==NULL) + return FALSE; + else + return TRUE; +} + + +/////////////////////////////////////////////// +// Functions to search tree and replace values +/////////////////////////////////////////////// + + +// Goes through the tree, and changes old messageID's to the new one +int CDallasMainDlg::UpdateStringParams(HTREEITEM root, char *old_name, char *new_name) +{ + HTREEITEM child; + tTreeNodeData *data; + int num_changed; + + if(root==NULL) return 0; + + // Process the children + num_changed=0; + child=m_ScriptTree.GetChildItem(root); + while(child!=NULL) { + num_changed+=UpdateStringParams(child,old_name,new_name); + + // Check this child to see if it's a string parameter in need of updating + data=(tTreeNodeData *)m_ScriptTree.GetItemData(child); + if(data!=NULL && data->type==PARAMETER_NODE && data->ID==STRING_PARAMETER_TYPE) { + if(strcmp(data->str_val,old_name)==0) { + strcpy(data->str_val,new_name); + UpdateAllParentNodesText(child); + num_changed++; + } + } + + // Get the next child + child=m_ScriptTree.GetNextSiblingItem(child); + } + + if(num_changed>0) SetModified(TRUE); + + return(num_changed); +} + + +/////////////////////////////////////////////////////////////////// +// Functions to Handle Script Drag-n-Drop +/////////////////////////////////////////////////////////////////// + +bool CDallasMainDlg::IsDropSource(HTREEITEM item) +{ + if(item==NULL) return FALSE; + + // See if it's an action node + if(GetNodeType(item)==ACTION_STATEMENT_NODE) { + HTREEITEM parent; + + // Make sure it's not in the clipboard + parent=GetParentNodeOfType(item,SCRIPT_HEADER_NODE); + if(parent==NULL) return FALSE; + + if(m_ScriptTree.GetParentItem(parent)!=NULL) return FALSE; + + return TRUE; + } + + // Make sure it's a script header node + if(GetNodeType(item)!=SCRIPT_HEADER_NODE) return FALSE; + + // Make sure it's not in the Clipboard + if(m_ScriptTree.GetParentItem(item)!=NULL) return FALSE; + + return TRUE; +} + +HTREEITEM CDallasMainDlg::GetDropTarget(HTREEITEM item) +{ + HTREEITEM target_item, parent_item; + + if(item==NULL || m_hitemDrag==NULL) return NULL; + + // See if the dragged node is an action + if(GetNodeType(m_hitemDrag)==ACTION_STATEMENT_NODE) { + tTreeNodeData *data; + HTREEITEM parent; + + // Make sure it's not in the clipboard + parent=GetParentNodeOfType(item,SCRIPT_HEADER_NODE); + if(parent==NULL) return NULL; + + if(m_ScriptTree.GetParentItem(parent)!=NULL) return NULL; + + // Make sure it's a valid drop node + data=(tTreeNodeData *)m_ScriptTree.GetItemData(item); + if(data==NULL) return NULL; + + if(data->type==ACTION_STATEMENT_NODE || (data->type==CONDITIONAL_HEADER_NODE && data->ID==NESTED)) + return(item); + + if(data->type==ACTIONS_HEADER_NODE) + return(item); + + return NULL; + } + + // See if it's the clipboard + if(GetNodeType(item)==CLIPBOARD_HEADER_NODE) return(item); + + // Get the script header for the selected node + target_item=GetParentNodeOfType(item,SCRIPT_HEADER_NODE); + if(target_item==NULL) return NULL; + + parent_item=m_ScriptTree.GetParentItem(target_item); + if(m_ScriptTree.GetParentItem(target_item)==NULL) return(target_item); + + if(GetNodeType(parent_item)==CLIPBOARD_HEADER_NODE) return(parent_item); + + return NULL; +} + +void CDallasMainDlg::OnBegindragEventTree(NMHDR* pNMHDR, LRESULT* pResult) +{ + NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; + + m_hitemDrag = pNMTreeView->itemNew.hItem; + m_hitemDrop = NULL; + m_ScriptTree.SelectItem( m_hitemDrag ); + + if (!IsDropSource(m_hitemDrag)) return; + + // get the image list for dragging + m_pDragImage = m_ScriptTree.CreateDragImage(m_hitemDrag); + + // CreateDragImage() returns NULL if no image list + // associated with the tree view control + if(!m_pDragImage) return; + + m_bLDragging = TRUE; + m_pDragImage->BeginDrag(0, CPoint(0,0)); + POINT pt = pNMTreeView->ptDrag; + m_ScriptTree.ClientToScreen( &pt ); + m_pDragImage->DragEnter(NULL, pt); + SetCapture(); + + *pResult = 0; +} + +void CDallasMainDlg::OnMouseMove(UINT nFlags, CPoint point) +{ + HTREEITEM hitem; + UINT flags; + + if (m_bLDragging) { + POINT pt = point; + ClientToScreen(&pt); + POINT tree_pt = pt; + m_ScriptTree.ScreenToClient( &tree_pt ); + CImageList::DragMove(pt); + if ((hitem = m_ScriptTree.HitTest(tree_pt, &flags)) != NULL) { + CImageList::DragShowNolock(FALSE); + m_hitemDrop = GetDropTarget(hitem); + m_ScriptTree.SelectDropTarget(m_hitemDrop); + CImageList::DragShowNolock(TRUE); + } + else { + CImageList::DragShowNolock(FALSE); + m_hitemDrop = NULL; + m_ScriptTree.SelectDropTarget(m_hitemDrop); + CImageList::DragShowNolock(TRUE); + } + } + + CDialog::OnMouseMove(nFlags, point); +} + +void CDallasMainDlg::OnLButtonUp(UINT nFlags, CPoint point) +{ + if (m_bLDragging) { + m_bLDragging = FALSE; + CImageList::DragLeave(this); + CImageList::EndDrag(); + ReleaseCapture(); + delete m_pDragImage; + + // Remove drop target highlighting + m_ScriptTree.SelectDropTarget(NULL); + + if((m_hitemDrag == m_hitemDrop) || m_hitemDrop==NULL) return; + + // See if the dragged node is an action + if(GetNodeType(m_hitemDrag)==ACTION_STATEMENT_NODE) { + HTREEITEM new_action_node, parent; + tTreeNodeData *data; + + data=(tTreeNodeData *)m_ScriptTree.GetItemData(m_hitemDrop); + if(data==NULL) return; + + if(data->type==ACTION_STATEMENT_NODE || (data->type==CONDITIONAL_HEADER_NODE && data->ID==NESTED)) + new_action_node=CopyTree(m_ScriptTree.GetParentItem(m_hitemDrop),m_hitemDrop,m_hitemDrag); + else if(data->type==ACTIONS_HEADER_NODE) { + new_action_node=CopyTree(m_hitemDrop,TVI_LAST,m_hitemDrag); + } + + if(new_action_node==NULL) return; + UpdateAllParentNodesText(new_action_node); + m_ScriptTree.SelectItem(new_action_node); + + // Delete the old action + parent=m_ScriptTree.GetParentItem(m_hitemDrag); + FreeTreeItem(m_hitemDrag); + + ConfirmAfterDelete(parent); + SetModified(TRUE); + + return; + } + + // Copy the tree to its new location (and select it) + HTREEITEM new_script_header=CopyTree(TVI_ROOT,m_hitemDrop,m_hitemDrag); + if(new_script_header==NULL) return; + UpdateAllParentNodesText(new_script_header); + m_ScriptTree.SelectItem(new_script_header); + + // Delete the old tree + FreeTreeItem(m_hitemDrag); + SetModified(TRUE); + } + + CDialog::OnLButtonUp(nFlags, point); +} + + +/////////////////////////////////////////////////////////////////// +// Functions to Handle Highlight Interface +/////////////////////////////////////////////////////////////////// + +void CDallasMainDlg::ClearHighlightRadioButtons(void) +{ + ((CButton *) GetDlgItem(IDC_NONE_RADIO))->SetCheck(0); + ((CButton *) GetDlgItem(IDC_SPECIFIC_RADIO))->SetCheck(0); + ((CButton *) GetDlgItem(IDC_LEVEL_RADIO))->SetCheck(0); + ((CButton *) GetDlgItem(IDC_ALLOBJ_RADIO))->SetCheck(0); + ((CButton *) GetDlgItem(IDC_ALLTRIG_RADIO))->SetCheck(0); +} + +void CDallasMainDlg::FillHighlightEventList(void) +{ + int i, index; + + m_EventList.ResetContent(); + + // Add the "all events" type + index=m_EventList.AddString("All Event Types"); + if(index!=LB_ERR) { + m_EventList.SetItemData(index,ALL_EVENT_TYPES); + } + + // Fill the list with the event types + for (i=0;event_info[i].type>=0;i++) { + index=m_EventList.AddString(event_info[i].name); + if(index!=LB_ERR) { + m_EventList.SetItemData(index,event_info[i].type); + } + } + + SetHighlightedEvent(ALL_EVENT_TYPES); +} + +int CDallasMainDlg::GetHighlightedEvent(void) +{ + int index=m_EventList.GetCurSel(); + if(index==LB_ERR) + return ALL_EVENT_TYPES; + + return(m_EventList.GetItemData(index)); +} + +void CDallasMainDlg::SetHighlightedEvent(int type) +{ + int index, total; + + total=m_EventList.GetCount(); + for(index=0;index=1) + returned_node=ParseScriptNodeLine_v1U(line,linenum,current_parent,skip_children,version,insert_before); + else + returned_node=ParseScriptNodeLine_v0(line,linenum,current_parent,skip_children,insert_before); + + if(returned_node!=NULL ) { + if(new_script_header==NULL) + new_script_header=returned_node; + last_node_added=returned_node; + last_node_childless=TRUE; + UpdateNodeText(last_node_added); + } + else + ScriptFileParseError(INVALID_NODE_ERR,linenum,0,NULL); + + if(returned_node==NULL || skip_children) { + skip_children=TRUE; + skip_depth=0; + } + } + } + + if (!done) + ScriptFileParseError(UEOS_ERR,linenum,0,NULL); + } + } + + cfclose(infile); + + // Change the script ID for the new script + if(new_script_header!=NULL) { + tTreeNodeData *data=(tTreeNodeData *)m_ScriptTree.GetItemData(new_script_header); + if(data!=NULL && data->type==SCRIPT_HEADER_NODE) { + int new_id=GetLowestUnusedScriptID(); + data->ID=new_id; + UpdateNodeText(new_script_header); + HighlightScript(new_script_header); + + if(new_id==m_NextScriptID) m_NextScriptID++; + + m_ScriptTree.SelectItem(new_script_header); + AssignSpecificValue(); + SetModified(TRUE); + } + } + + return TRUE; +} + +#define TEMP_EXPORT_FNAME "DExport.tmp" + +// Adds selected script to specified library file +bool CDallasMainDlg::ExportScriptToFile(char *filename, char *script_name) +{ + CFILE *infile; + char linebuf[2048]; + char *line; + int linenum; + int valid_lines_read; + HTREEITEM selected_node, script_header_node; + bool ReplacingScript; + bool ScriptReplaced; + + CurrentParsingFilename=filename; + + // Make sure the selected item is valid for exporting + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return FALSE; + script_header_node=GetParentNodeOfType(selected_node,SCRIPT_HEADER_NODE); + if(script_header_node==NULL) return FALSE; + + // Make sure library file can be written to + if(_access(filename,0) != -1) { + if( (_access( filename, 2 )) == -1 ) { + CString msg; + msg.Format("The library file \"%s\" is read-only!",filename); + MessageBox(msg,"Script Library File Not Writeable!",MB_OK|MB_ICONEXCLAMATION); + return FALSE; + } + } + + // Try to open the file for reading + infile=cfopen (filename,"rt"); + + // Try to open the temp file for writing + CurrentOutputFile = cfopen(TEMP_EXPORT_FNAME,"wt"); + if(CurrentOutputFile==NULL) { + CString msg, title; + msg.Format("ERROR: Unable to open %s for output.",TEMP_EXPORT_FNAME); + title.Format("Temp File Save Error!"); + MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); + if(infile!=NULL) cfclose(infile); + return FALSE; + } + + // If file doesn't exist, Write out the header info + if(infile==NULL) { + O(("/////////////////////////////////////////////////////////////////////")); + O(("// D.A.L.L.A.S. Generated Script Library File ")); + O(("/////////////////////////////////////////////////////////////////////")); + O((" ")); + } + + linenum=0; + ReplacingScript=FALSE; + ScriptReplaced=FALSE; + + // Read in and parse each line of the file + while (infile!=NULL && !cfeof(infile)) { + + // Clear the buffer + strcpy(linebuf,""); + + // Read in a line from the file + cf_ReadString(linebuf, sizeof(linebuf), infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + // Check for Start of Script Block Section + if (strncmp(line,SCRIPT_START_TAG,strlen(SCRIPT_START_TAG)) == 0) { + bool done = false; + + // Write out the start tag + O(("%s",linebuf)); + + // Set valid line counter to track whether we're reading header info or tree nodes + valid_lines_read=0; + + // Read all the lines in the block + while (!done && !cfeof(infile)) { + + strcpy(linebuf,""); + cf_ReadString(linebuf,sizeof(linebuf),infile); + linenum++; + + // Remove whitespace padding at start and end of line + RemoveTrailingWhitespace(linebuf); + line=SkipInitialWhitespace(linebuf); + + // If it's an empty line or a comment, skip it + if(strlen(line)==0 || strncmp(line,"//",2)==0) { + if(!ReplacingScript) + O(("%s",linebuf)); + continue; + } + + // Check for End of Script Block Section + if (strncmp(line,SCRIPT_END_TAG,strlen(SCRIPT_END_TAG)) == 0) { + if(ReplacingScript) { + ScriptReplaced=TRUE; + ReplacingScript=FALSE; + } + O(("%s",linebuf)); + done=true; + continue; + } + + // See if this script's name matches the given name + if(valid_lines_read==0) { + if(stricmp(line,script_name)==0) { + CString msg, title; + + msg.Format("A script named '%s' already exists in this library.\n\nWould you like to replace it with your new script?",script_name); + title.Format("Duplicate Script Name Encountered"); + + // Prompt user to see if it should be replaced + if(MessageBox(msg,title,MB_YESNO|MB_ICONQUESTION)==IDNO) { + cfclose(infile); + cfclose(CurrentOutputFile); + CurrentOutputFile=NULL; + ddio_DeleteFile(TEMP_EXPORT_FNAME); + return FALSE; + } + + // Copy the new script into it's place + O(("%s",script_name)); + O(("VERSION %d",DALLAS_SAVE_VERSION)); + + CurrentTabLevel=0; + if(DALLAS_SAVE_VERSION>=1) + WriteScriptNodeDump_v1U(script_header_node,TRUE); + else + WriteScriptNodeDump_v0(script_header_node); + WriteScriptChildrenDump(script_header_node,TRUE); + + ReplacingScript=TRUE; + } + else + O(("%s",linebuf)); + + valid_lines_read++; + continue; + } + + if(!ReplacingScript) + O(("%s",linebuf)); + } + + if (!done) + ScriptFileParseError(UEOS_ERR,linenum,0,NULL); + } + else + O(("%s",linebuf)); + } + + // If the script wasn't replaced, add it at the end + if(!ScriptReplaced) { + O(("%s",SCRIPT_START_TAG)); + O(("%s",script_name)); + O(("VERSION %d",DALLAS_SAVE_VERSION)); + + CurrentTabLevel=0; + if(DALLAS_SAVE_VERSION>=1) + WriteScriptNodeDump_v1U(script_header_node,TRUE); + else + WriteScriptNodeDump_v0(script_header_node); + WriteScriptChildrenDump(script_header_node,TRUE); + + O(("%s",SCRIPT_END_TAG)); + O((" ")); + } + + if(infile!=NULL) cfclose(infile); + + cfclose(CurrentOutputFile); + CurrentOutputFile=NULL; + + // Now delete the library input file, and replace it with the temp file + ddio_DeleteFile(filename); + if(!CopyFile(TEMP_EXPORT_FNAME,filename,FALSE)) { + CString msg, title; + msg.Format("ERROR: Could not copy over temporary library file.\n\nThe export failed."); + title.Format("Script Export Error!"); + MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); + } + else { + CString msg, title; + msg.Format("The script was exported successfully!"); + title.Format("Script Export Successful"); + MessageBox(msg,title,MB_OK|MB_ICONINFORMATION); + } + + ddio_DeleteFile(TEMP_EXPORT_FNAME); + + return TRUE; +} + + +// Imports a script from a specified Library file +void CDallasMainDlg::OnImportButton() +{ + HTREEITEM selected_node, initial_insert_before; + CString library_filename; + + // Make sure the selected item is valid for importing + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + if(GetNodeType(selected_node)==CLIPBOARD_HEADER_NODE) + initial_insert_before=selected_node; + else { + initial_insert_before=GetParentNodeOfType(selected_node,SCRIPT_HEADER_NODE); + if(initial_insert_before==NULL) return; + if(m_ScriptTree.GetParentItem(initial_insert_before)!=NULL) return; + } + + // Display file selection dlg + if(!ScriptLibraryFilePrompt(library_filename,TRUE)) return; + + // Scan the file and display scripts that can be imported + CDallasImportDlg dlg; + dlg.m_Filename=library_filename; + if(dlg.DoModal()==IDCANCEL) return; + if(dlg.m_ScriptName.IsEmpty()) return; + + // Try to import the selected script + ImportScriptFromFile(library_filename.GetBuffer(0),dlg.m_ScriptName.GetBuffer(0)); +} + + +// Exports a script to a specified Library file +void CDallasMainDlg::OnExportButton() +{ + HTREEITEM selected_node, script_header_node; + CString library_filename; + + // Make sure the selected item is valid for exporting + selected_node=m_ScriptTree.GetSelectedItem(); + if(selected_node==NULL) return; + script_header_node=GetParentNodeOfType(selected_node,SCRIPT_HEADER_NODE); + if(script_header_node==NULL) return; + + // Display the enter name prompt + CDallasGenericPromptDlg dlg; + dlg.m_DialogTitle="Exported Script Name Prompt"; + dlg.m_PromptText="Enter the name for this exported script:"; + dlg.m_PromptData=""; + dlg.m_MaxDataLength=256; + + if(dlg.DoModal()==IDCANCEL) return; + if(dlg.m_PromptData.IsEmpty()) return; + + // Display file selection dlg + if(!ScriptLibraryFilePrompt(library_filename,FALSE)) return; + + // Try to export the selected script to the specified library file + ExportScriptToFile(library_filename.GetBuffer(0),dlg.m_PromptData.GetBuffer(0)); +} + +CDallasMainDlg *GetDallasDialogPtr(void) +{ +#ifdef NEWEDITOR + CNewEditorApp *editor_app; + editor_app = (CNewEditorApp *)AfxGetApp(); +#else + CEditorApp *editor_app; + editor_app = &theApp; +#endif + + return editor_app->m_DallasModelessDlgPtr; +} diff --git a/editor/DallasMainDlg.h b/editor/DallasMainDlg.h new file mode 100644 index 00000000..6ae8e53a --- /dev/null +++ b/editor/DallasMainDlg.h @@ -0,0 +1,1553 @@ +/* +* $Logfile: /DescentIII/Main/editor/DallasMainDlg.h $ +* $Revision: 1.1.1.1 $ +* $Date: 2003-08-26 03:57:37 $ +* $Author: kevinb $ +* +* This is the header for the main dialog of the DALLAS graphical scripting interface +* +* $Log: not supported by cvs2svn $ + * + * 67 8/30/99 4:11p Nate + * Added copy/paste for conditions, log ops, and nested if-then clauses + * + * 66 5/04/99 6:53p Jeff + * added event for when a player dies + * + * 65 4/27/99 4:27p Jeff + * added player respawn osiris event + * + * 64 4/15/99 9:47p Nate + * Upped max number of enum values to 100 + * + * 63 4/14/99 6:03p Nate + * Added Event Type specification to Dallas Script Highlighting system. + * + * 62 4/02/99 2:16p Nate + * Added AI Init event + * + * 61 3/30/99 4:47p Jeff + * added level events for when IGC occurs for a player + * + * 60 3/11/99 10:51a Nate + * Added deletion of "Untitled" Dallas files when doing a New from editor + * + * 59 2/22/99 1:17p Nate + * Added 'level goal item complete' event + * + * 58 2/22/99 1:19a Jeff + * added handling for evt_use + * + * 57 2/20/99 6:07p Nate + * Added Level Goal events + * + * 56 2/19/99 5:35p Nate + * Added new types and events + * + * 55 2/17/99 4:14p Nate + * Added condition query shortcuts + * + * 54 2/08/99 3:53p Nate + * Added new event types + * + * 53 2/07/99 4:43p Nate + * Added OWNER selection to Door parameter types + * + * 52 2/05/99 11:52a Nate + * Added importing/exporting of scripts + * + * 51 2/03/99 7:20p Nate + * Fixed clipboard bug and added script chaining option + * + * 50 2/03/99 2:19p Nate + * Added cool drag-n-drop support + * + * 49 2/03/99 11:57a Nate + * Added script highlighting interface + * + * 48 2/02/99 7:41p Nate + * Added columnization of popup menus + * + * 47 2/01/99 2:42p Nate + * Added title bar display of level and modified indicator + * + * 46 1/29/99 4:41p Nate + * A few minor tweaks and fixes + * + * 45 1/28/99 9:41p Nate + * Added tons of new stuff + * + * 44 1/26/99 1:15p Nate + * Added UserTypes Workshop implementation + * + * 43 1/25/99 7:16p Nate + * Added UserTypes dialog (non-functional) + * + * 42 1/25/99 2:38p Nate + * Added Valid Flag Mask range support. + * + * 41 1/25/99 9:52a Nate + * Enabled Save Format Version 1 + * + * 40 1/24/99 4:49p Nate + * Added code for Dallas Save Format Version 1, but didn't enable it yet + * + * 39 1/23/99 5:52p Nate + * Added flag support + * + * 38 1/21/99 8:57p Nate + * Added warnings when saving objects + * + * 37 1/20/99 3:51p Nate + * Added Specific Name parameter type 'a' + * + * 36 1/19/99 7:37p Nate + * Added sound selection prompt dialog + * + * 35 1/19/99 12:18p Nate + * Made it so Owner objects can now be "other" + * + * 34 1/19/99 10:35a Nate + * Fixed Other object submenu bug + * + * 33 1/18/99 2:29p Nate + * Added support for default parameters and valid range specification + * + * 32 1/17/99 6:29p Nate + * Layed groundwork for default parameter values and valid parameter + * ranges + * + * 31 1/15/99 7:31p Nate + * Added some more interface features/fixes + * + * 30 1/15/99 2:05p Nate + * Added collapse/expand all, fixed me and delete problems, made dlg + * longer + * + * 29 1/15/99 10:37a Nate + * Fixed highest room index bug + * + * 28 1/14/99 6:11p Nate + * Added Trigger Script support and many other things, too numerous to + * count. + * + * 27 1/13/99 7:28p Nate + * Added message file reading from created script + * + * 26 1/13/99 10:50a Nate + * Fixed up copy/pase, added highlighting of all scripts matching + * specified owner + * + * 25 1/12/99 7:32p Nate + * Added copy and paste support + * + * 24 1/12/99 4:45p Nate + * Added max exec time support, added more interface features + * + * 23 1/11/99 8:42p Nate + * Added script parameter support + * + * 22 1/11/99 6:40p Nate + * Added ENUM support + * + * 21 1/11/99 10:19a Nate + * Fixed AND/OR insertion bug + * + * 20 1/08/99 12:32p Nate + * Added glue function validation upon loading scripts + * + * 19 1/07/99 10:17p Nate + * Added first round of script loading code... + * + * 18 1/06/99 7:09p Nate + * Added saving of scripts + * + * 17 1/06/99 1:13p Nate + * Added support for IT objects and ELSE clauses + * + * 16 1/05/99 8:00p Nate + * Added conditional code creation... fixed up interface yet a little + * more. + * + * 15 1/05/99 2:03p Nate + * Fixed up events and conditional interface a little + * + * 14 1/04/99 7:34p Nate + * Added rough interface for Conditions + * + * 13 12/23/98 6:44p Nate + * Added reading in of queries + * + * 12 12/23/98 4:03p Nate + * Added code to implement as a modeless dialog + * + * 11 12/23/98 12:35p Nate + * Added use of level name in Dallas script file naming system. + * + * 10 12/22/98 3:55p Nate + * Added object and room assignments + * + * 9 12/21/98 8:01p Nate + * Added creation of shell code, started conditional interface. + * + * 8 12/20/98 4:29p Nate + * Added script grouping code (based upon owner, then event type) + * + * 7 12/18/98 6:54p Nate + * Added more interface features. + * + * 6 12/17/98 9:48p Nate + * Added editing of paramaters + * + * 5 12/16/98 8:45p Nate + * Added loading of Actions + * + * 4 12/15/98 7:47p Nate + * Added inserting and deleting of default script trees. + * + * 3 12/13/98 6:08p Nate + * Implemented the Message List interface + * + * 2 12/11/98 6:45p Nate + * Initial Version +* +* $NoKeywords: $ +*/ + + +#if !defined(AFX_DALLASMAINDLG_H__93285122_90E1_11D2_A4E0_00A0C96ED60D__INCLUDED_) +#define AFX_DALLASMAINDLG_H__93285122_90E1_11D2_A4E0_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DallasMainDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// The Current Save Version Number +///////////////////////////////////////////////////////////////////////////// +#define DALLAS_SAVE_VERSION 3 + +///////////////////////////////////////////////////////////////////////////// +// Message List structure and constants +///////////////////////////////////////////////////////////////////////////// + +#define MAX_MESSAGE_LIST_ENTRIES 500 +#define MAX_MESSAGE_LEN 256 +#define MAX_MESSAGE_NAME_LEN 45 + +#define NO_MSG_LIST_ERROR 0 +#define MSG_LIST_FULL_ERROR 1 +#define MSG_LIST_DUP_NAME_ERROR 2 + +#define DEFAULT_MESSAGE_NAME "Message" +#define DEFAULT_MESSAGE_TEXT "" + +typedef struct { + char name[MAX_MESSAGE_NAME_LEN+1]; // the named identifier of the message + char message[MAX_MESSAGE_LEN+1]; // the message text +} tMessageListEntry; + + +///////////////////////////////////////////////////////////////////////////// +// Tree Data Node structure and constants +///////////////////////////////////////////////////////////////////////////// + +#define NOT_SPECIFIED_TYPE -1 +#define OBJECT_NONE_HANDLE -2 +#define OBJECT_IT_HANDLE -3 +#define OBJECT_ME_HANDLE -4 +#define ENUM_GOALID_VALUE -5 +#define ENUM_TIMERID_VALUE -6 +#define ENUM_MATCENID_VALUE -7 +#define MATCEN_ID_VALUE -8 +#define LEVEL_GOAL_ID_VALUE -9 + +// The types of Tree Nodes +#define SCRIPT_HEADER_NODE 0 +#define SCRIPT_OWNER_NODE 1 +#define SCRIPT_EVENT_NODE 2 +#define CONDITIONAL_HEADER_NODE 3 +#define ACTIONS_HEADER_NODE 4 +#define CONDITIONAL_STATEMENT_NODE 5 +#define EXPRESSION_NODE 6 +#define EXPRESSION_OPERATOR_NODE 7 +#define ACTION_STATEMENT_NODE 8 +#define LOGICAL_OPERATOR_NODE 9 +#define PARAMETER_NODE 10 +#define PARAMETER_OPERATOR_NODE 11 +#define CLIPBOARD_HEADER_NODE 12 +#define UNKNOWN_NODE 13 + +// Logical Operator Types +#define AND_TYPE 0 +#define OR_TYPE 1 + +#define MAX_LOGICAL_OPERATORS 2 + +// Conditional Statement Types +#define ALWAYS_STATEMENT 0 +#define BINARY_STATEMENT 1 +#define COMPARISON_STATEMENT 2 + +#define MAX_CONDITION_TYPES 3 + +#define ALWAYS_STRING "ALWAYS" + +// Parameter Types +#define DOOR_PARAMETER_TYPE 0 +#define OBJECT_PARAMETER_TYPE 1 +#define ROOM_PARAMETER_TYPE 2 +#define TRIGGER_PARAMETER_TYPE 3 +#define INT_PARAMETER_TYPE 4 +#define BOOL_PARAMETER_TYPE 5 +#define FLOAT_PARAMETER_TYPE 6 +#define VECTOR_PARAMETER_TYPE 7 +#define STRING_PARAMETER_TYPE 8 +#define PERCENTAGE_PARAMETER_TYPE 9 +#define ENUM_PARAMETER_TYPE 10 +#define SCRIPT_PARAMETER_TYPE 11 +#define SOUND_PARAMETER_TYPE 12 +#define SPECNAME_PARAMETER_TYPE 13 +#define TEXTURE_PARAMETER_TYPE 14 +#define FLAG_PARAMETER_TYPE 15 +#define PATH_PARAMETER_TYPE 16 +#define MATCEN_PARAMETER_TYPE 17 +#define LEVEL_GOAL_PARAMETER_TYPE 18 +#define STRM_AUDIO_PARAMETER_TYPE 19 +#define UNKNOWN_PARAMETER_TYPE 20 + +#define MAX_LITERALS 20 + +#define ANY_PARAMETER_TYPE 21 + +// Expression Types +#define LITERAL_VALUE_TYPE 0 +#define QUERY_TYPE 1 + +// Expression Operator Types +#define BINARY_OPERATOR_TYPE 0 +#define COMPARISON_OPERATOR_TYPE 1 + +// Expression Operators (Comparison) +#define EQUAL_TO 0 +#define NOT_EQUAL_TO 1 +#define GREATER_THAN 2 +#define LESS_THAN 3 +#define GREATER_THAN_OR_EQUAL_TO 4 +#define LESS_THAN_OR_EQUAL_TO 5 + +// Expression Operators (Binary) +#define IS_TRUE 6 +#define IS_FALSE 7 + +#define MAX_EXPRESSION_OPERATORS 8 + +// Struct for storing expression operator information +typedef struct { + int type; // expression operator (see above) + char *name; // the displayed name + char *menu_name; // the menu name + char *code_name; // DEFINE string to identify event in code + int op_type; // whether it is a binary or comparison op +} ExpOpInfoItem; + + +// Script Owner Types +#define TRIGGER_TYPE 0 +#define OBJECT_TYPE 1 +#define LEVEL_TYPE 2 + +#define ROOM_TYPE 3 // Not an owner type, but it is a named type +#define SOUND_TYPE 4 // also not an owner type +#define PATH_TYPE 5 // also not an owner type +#define MATCEN_TYPE 6 // also not an owner type +#define LEVEL_GOAL_TYPE 7 // also not an owner type + +#define ALL_OBJECTS_TYPE 10 // Used for highlighting purposes only +#define ALL_TRIGGERS_TYPE 11 // Used for highlighting purposes only +#define NONE_TYPE 12 // Used for highlighting purposes only +#define ALL_OWNERS_TYPE 13 // Used for highlighting purposes only + +// Script Event Types - ONLY ADD TO END OF LIST!!!! +// (NOTE: when making changes, remember to update event_info[] in the main source file!) +#define COLLIDE_EVENT_TYPE 0 +#define ACTIVATED_EVENT_TYPE 1 +#define CREATED_EVENT_TYPE 2 +#define DAMAGED_EVENT_TYPE 3 +#define DESTROYED_EVENT_TYPE 4 +#define FRAME_INTERVAL_EVENT_TYPE 5 +#define LEVEL_START_EVENT_TYPE 6 +#define LEVEL_END_EVENT_TYPE 7 +#define CHANGE_SEGMENT_EVENT_TYPE 8 +#define TIMER_EVENT_TYPE 9 +#define AIN_OBJKILLED_EVENT_TYPE 10 +#define AIN_SEEPLAYER_EVENT_TYPE 11 +#define AIN_WHITOBJECT_EVENT_TYPE 12 +#define AIN_GOALCOMPLETE_EVENT_TYPE 13 +#define AIN_GOALFAIL_EVENT_TYPE 14 +#define AIN_MELHIT_EVENT_TYPE 15 +#define AIN_MELATTACKFRAME_EVENT_TYPE 16 +#define AIN_MOVIE_STARTED_EVENT_TYPE 17 +#define AIN_MOVIE_ENDED_EVENT_TYPE 18 +#define DOOR_CLOSED_EVENT_TYPE 19 +#define DOOR_ACTIVATED_EVENT_TYPE 20 +#define MATCEN_NOTIFY_EVENT_TYPE 21 +#define CHILD_DIED_EVENT_TYPE 22 +#define LGOAL_COMPLETED_EVENT_TYPE 23 +#define ALL_LGOALS_COMPLETE_EVENT_TYPE 24 +#define USED_EVENT_TYPE 25 +#define LGOAL_ITEM_COMPLETE_EVENT_TYPE 26 +#define PLAYER_MOVIE_START_TYPE 27 +#define PLAYER_MOVIE_END_TYPE 28 +#define AI_INIT_EVENT_TYPE 29 +#define PLAYER_RESPAWN_TYPE 30 +#define PLAYER_DIES_TYPE 31 +#define MAX_EVENT_TYPES 32 + +#define ALL_EVENT_TYPES 99 // Used for highlighting purposes only + +// Struct for storing event information +typedef struct { + int type; // event type (see above) + char *name; // the displayed name + char *code_name; // DEFINE string to identify event in code + char *data_line; // The line for this event's data struct + int flags; // owner and various flags +} EventInfoItem; + +// Constants for masking what events go with what owner +#define OBJECT_MASK 0x001 +#define TRIGGER_MASK 0x002 +#define LEVEL_MASK 0x004 + +#define HAS_IT_MASK 0x008 +#define HAS_GOALID_MASK 0x010 +#define HAS_TIMERID_MASK 0x020 +#define HAS_MATCENID_MASK 0x040 + +#define DOOR_OBJECT_MASK 0x080 + +#define HAS_LEVGOALID_MASK 0x100 + + +// Struct for easily creating literal menu +typedef struct { + int type; // the type of literal (parameter type) + char *name; // menu name of the literal +} ParamMenuItem; + + +// Nested Types +#define TOP_LEVEL 0 +#define NESTED 1 + +// Clause Types +#define THEN_CLAUSE 0 +#define ELSE_CLAUSE 1 + +// Max Execution Time options +#define ENTER_EXEC_TIMES 0 +#define EXECUTE_INFINITELY 1 +#define EXECUTE_ONCE 2 +#define EXECUTE_TWICE 3 + +#define MAX_EXEC_TIME_OPTIONS 4 + +// Continue Chain Options +#define CONTINUE_SCRIPT_CHAIN 0 +#define BREAK_SCRIPT_CHAIN 1 + +#define MAX_CHAIN_OPTIONS 2 + +// Object Parameter Indicators +#define USE_OBJECT_HANDLE 0 +#define USE_IT_HANDLE 1 +#define USE_ME_HANDLE 2 + +// Enum Parameter Indicators +#define USE_ENUM_VALUE 0 +#define USE_GOALID_VALUE 1 +#define USE_TIMERID_VALUE 2 +#define USE_MATCENID_VALUE 3 + +// Matcen Parameter Indicators +#define USE_MATCEN_VALUE 0 +#define USE_MATCEN_EVENT_ID 1 + +// Level Goal Parameter Indicators +#define USE_LEVEL_GOAL_VALUE 0 +#define USE_LEVEL_GOAL_ID 1 + +#define DEFAULT_SCRIPT_HEADER_STRING "Script Description Goes Here" +#define NOT_SPECIFIED_STRING "NOT SPECIFIED" +#define NONE_STRING "None" + +#define MAX_NDATA_NAME_LEN 64 + +#define MAX_STRING_DISPLAY_LEN 20 + +typedef struct { + int type; // the node type (see above list) + char name[MAX_NDATA_NAME_LEN+1]; // multipurpose name string + int ID; // multipurpose identifier + int subID; // multipurpose sub-identifier + int int_val; // stores an integer value + float float_val1; // stores a float value type (Vector X) + float float_val2; // stores a float value type (Vector Y) + float float_val3; // stores a float value type (Vector Z) + char str_val[MAX_MESSAGE_NAME_LEN+1]; // stores the named identifier of a message + int flags; // various flags +} tTreeNodeData; + +/********************************************************** +* Tree Node Data Specifications +*********************************************************** + + SCRIPT_HEADER_NODE + name: the script header description entered by user + ID: the ID number given to the script + + SCRIPT_OWNER_NODE + ID: the type of owner (object, trigger, or level) + int_val: the handle or ID number for the owner + + SCRIPT_EVENT_NODE + ID: the type of event + + CONDITIONAL_HEADER_NODE + ID: whether it is TOP_LEVEL or NESTED + + ACTIONS_HEADER_NODE + ID: whether it is TOP_LEVEL or NESTED + for TOP_LEVEL: + subID: max times to execute actions (only valid for TOP_LEVEL, 0 implies infinity) + int_val: whether it should + for NESTED: + subID: whether it is a THEN_CLAUSE or an ELSE_CLAUSE + int_val: unused + + CONDITIONAL_STATEMENT_NODE + ID: the type of conditional (always, binary, or comparison statement) + + EXPRESSION_NODE + ID: stores index into the Query Database + name: the parameter name accepting the query's return value + + EXPRESSION_OPERATOR_NODE + ID: the type of operation (binary or comparison) + subID: the specific operation (<,=,>, etc) + + ACTION_STATEMENT_NODE + ID: index into the Action Database (or DO_NOTHING_ID) + + LOGICAL_OPERATOR_NODE + ID: the type of operator (AND, OR) + + PARAMETER_NODE + name: the parameter name for this value + ID: the type of parameter this node is storing + for DOOR_PARAMETER_TYPE: + subID: indicates whether object should USE_OBJECT_HANDLE or USE_IT_HANDLE or USE_ME_HANDLE + int_val: stores the object handle for the door + str_val: stores the name of the door + for OBJECT_PARAMETER_TYPE: + subID: indicates whether object should USE_OBJECT_HANDLE or USE_IT_HANDLE or USE_ME_HANDLE + int_val: stores the object handle + str_val: stores the name of the object + for ROOM_PARAMETER_TYPE: + int_val: stores an index/ID for the room + str_val: stores the name of the room + for TRIGGER_PARAMETER_TYPE: + int_val: stores an index/ID for the trigger + str_val: stores the name of the trigger + for INT_PARAMETER_TYPE: + int_val: stores an integer value + for BOOL_PARAMETER_TYPE: + int_val: stores either TRUE or FALSE + for FLOAT_PARAMETER_TYPE: + float_val1: stores a float value + for VECTOR_PARAMETER_TYPE: + float_val1: stores X value + float_val2: stores Y value + float_val3: stores Z value + for STRING_PARAMETER_TYPE: + str_val: stores the name (identifier) of a string in the message list + for PERCENTAGE_PARAMETER_TYPE: + float_val1: stores a percentage as a float value (ie 0.5 == 50%) + for ENUM_PARAMETER_TYPE: + subID: indicates whether enum should USE_ENUM_VALUE or USE_GOALID_VALUE or USE_TIMERID_VALUE or USE_MATCENID_VALUE + int_val: stores the value for the enumeration (keyed on the value in name) + for SCRIPT_PARAMETER_TYPE: + int_val: stores the script ID + for SOUND_PARAMETER_TYPE: + int_val: stores the sound array index position + str_val: stores the name of the sound + for SPECNAME_PARAMETER_TYPE: + str_val: stores the specific string + for TEXTURE_PARAMETER_TYPE: + int_val: stores the texture array index position + str_val: stores the name of the sound + for FLAG_PARAMETER_TYPE: + int_val: stores the value for the flags (keyed on the value in name) + for PATH_PARAMETER_TYPE: + int_val: stores an index/ID for the path + str_val: stores the name of the path + for MATCEN_PARAMETER_TYPE: + subID: indicates whether matcen should USE_MATCEN_VALUE or USE_MATCEN_EVENT_ID + int_val: stores an index/ID for the matcen + str_val: stores the name of the matcen + for LEVEL_GOAL_PARAMETER_TYPE: + subID: stores whether goal should USE_LEVEL_GOAL_VALUE or USE_LEVEL_GOAL_ID + int_val: stores an index/ID for the goal + str_val: stores the name of the goal + for STRM_AUDIO_PARAMETER_TYPE: + str_val: stores the name of the streaming audio file + + PARAMETER_OPERATOR_NODE + + CLIPBOARD_HEADER_NODE + + UNKNOWN_NODE +*************************************************************/ + + +///////////////////////////////////////////////////////////////////////////// +// Enumeration structures and constants +///////////////////////////////////////////////////////////////////////////// + +#define MAX_ENUMS 50 +#define MAX_ENUM_VALUES 100 + +#define TAG_ENUM "$$ENUM" +#define TAG_USERTYPE "$$USERTYPE" + +#define USERTYPE_NONE "None" + +#define INVALID_ENUM -1 + +typedef struct { + char *name; // the name of this enum value + int value; // the value bound to this name +} tEnumValueEntry; + +typedef struct { + char *name; // the name for this enumeration type + tEnumValueEntry values[MAX_ENUM_VALUES]; // the enumerated value storage + int num_values; // the number of values stored + bool is_user_type; // indicates if it's a user type + int max_values; // max allowed value for user types +} tEnumDBEntry; + + +///////////////////////////////////////////////////////////////////////////// +// Flag structures and constants +///////////////////////////////////////////////////////////////////////////// + +#define MAX_FLAGS 50 +#define MAX_FLAG_VALUES 32 + +#define TAG_FLAG "$$FLAG" + +#define INVALID_FLAG -1 + +typedef struct { + char *name; // the name of this flag value + int value; // the value bound to this name +} tFlagValueEntry; + +typedef struct { + char *name; // the name for this flag type + tFlagValueEntry values[MAX_FLAG_VALUES]; // the flag value storage + int num_values; // the number of values stored +} tFlagDBEntry; + + +///////////////////////////////////////////////////////////////////////////// +// Action and Query Database structures and constants +///////////////////////////////////////////////////////////////////////////// + +#define DO_NOTHING_ID -1 +#define DO_NOTHING_STRING "DO NOTHING" + +#define MAX_ACTIONS 500 +#define MAX_QUERIES 500 +#define MAX_CATEGORIES 32 + +#define INVALID_CATEGORY -1 + +#define INVALID_FUNCTION_NAME "InvalidFunctionName" +#define INVALID_FUNCTION_ID -2 + +#define TAG_CAT "$$CATEGORIES" +#define TAG_ACTION "$$ACTION" +#define TAG_QUERY "$$QUERY" +#define TAG_END "$$END" + +#define NO_MEM_ERR 0 // out of memory (malloc failed) +#define UEOF_ERR 1 // unexpected end of file +#define INV_CAT_ERR 2 // invalid category assigned +#define INV_ENUM_ERR 3 // invalid enum assigned (duplicate name) +#define INV_ENUM_VALUE_ERR 4 // invalid enum value assigned (duplicate) +#define MAX_ENUM_ERR 5 // the max number of enums has been reached +#define MAX_ENUM_VALUES_ERR 6 // the max number of enum values has been reached +#define INV_FLAG_ERR 7 // invalid flag assigned (duplicate name) +#define INV_FLAG_VALUE_ERR 8 // invalid flag value assigned (duplicate) +#define MAX_FLAG_ERR 9 // the max number of flags has been reached +#define MAX_FLAG_VALUES_ERR 10 // the max number of flag values has been reached + +//Structure that defines an action +typedef struct { + int category; //Which group this action belongs to + char *desc; //What the user sees + char *func; //The glue function to call for this action + char *help; //The help info for this function +} tActionDBEntry; + +//Structure that defines a query +typedef struct { + int category; //Which group this query belongs to + char *desc; //What the user sees + char *func; //The glue function to call for this query + char *help; //The help info for this function +} tQueryDBEntry; + +///////////////////////////////////////////////////////////////////////////// +// Script Sorting/Organization Structures and Constants +///////////////////////////////////////////////////////////////////////////// + +typedef struct { + HTREEITEM *script_node_list; // The list of scripts of this event type + int num_script_nodes; // The number of scripts in the list +} tEventSection; + + +typedef struct { + int owner_type; // The owner type for this script group + int owner_handle; // The specific handle/ID for this script group + tEventSection event_sections[MAX_EVENT_TYPES]; // The event section script lists +} tScriptOwnerGroup; + + +///////////////////////////////////////////////////////////////////////////// +// File parsing constants +///////////////////////////////////////////////////////////////////////////// + +// Message File Related +#define MAX_MSG_FILE_BUFFER_LEN (MAX_MESSAGE_LEN+MAX_MESSAGE_NAME_LEN)+1024 +#define NEXT_MSG_ID_NUM_KEYWORD "NEXT_MESSAGE_ID_NUMBER" + +// Usertype value block tags +#define USERTYPE_VALS_START_TAG "$$UTYPE_VALS_START" +#define USERTYPE_VALS_END_TAG "$$UTYPE_VALS_END" + +// Script Source File Related +#define SCRIPT_BLOCK_START_TAG "$$SCRIPT_BLOCK_START" +#define SCRIPT_BLOCK_END_TAG "$$SCRIPT_BLOCK_END" +#define CHILD_BLOCK_START_TAG "$$CHILD_BLOCK_START" +#define CHILD_BLOCK_END_TAG "$$CHILD_BLOCK_END" + +// Name List Constants +#define DOOR_LIST_START_TAG "$$DOOR_LIST_START" +#define DOOR_LIST_END_TAG "$$DOOR_LIST_END" + +#define OBJECT_LIST_START_TAG "$$OBJECT_LIST_START" +#define OBJECT_LIST_END_TAG "$$OBJECT_LIST_END" + +#define ROOM_LIST_START_TAG "$$ROOM_LIST_START" +#define ROOM_LIST_END_TAG "$$ROOM_LIST_END" + +#define TRIGGER_LIST_START_TAG "$$TRIGGER_LIST_START" +#define TRIGGER_LIST_END_TAG "$$TRIGGER_LIST_END" + +#define SOUND_LIST_START_TAG "$$SOUND_LIST_START" +#define SOUND_LIST_END_TAG "$$SOUND_LIST_END" + +#define TEXTURE_LIST_START_TAG "$$TEXTURE_LIST_START" +#define TEXTURE_LIST_END_TAG "$$TEXTURE_LIST_END" + +#define SPECNAME_LIST_START_TAG "$$SPECNAME_LIST_START" +#define SPECNAME_LIST_END_TAG "$$SPECNAME_LIST_END" + +#define PATH_LIST_START_TAG "$$PATH_LIST_START" +#define PATH_LIST_END_TAG "$$PATH_LIST_END" + +#define MATCEN_LIST_START_TAG "$$MATCEN_LIST_START" +#define MATCEN_LIST_END_TAG "$$MATCEN_LIST_END" + +#define GOAL_LIST_START_TAG "$$GOAL_LIST_START" +#define GOAL_LIST_END_TAG "$$GOAL_LIST_END" + +#define STRM_AUDIO_LIST_START_TAG "$$STRM_AUDIO_LIST_START" +#define STRM_AUDIO_LIST_END_TAG "$$STRM_AUDIO_LIST_END" + + +// Custom Source Related +#define CUSTOM_FUNCTION_PROTOTYPE_BEGIN_TAG "" +#define CUSTOM_FUNCTION_PROTOTYPE_END_TAG "" + +// Script Library File Parsing +#define SCRIPT_START_TAG "$$SCRIPT" +#define SCRIPT_END_TAG "$$END" + +// Script Parsing Errors +#define UEOS_ERR 0 // The script file ended unexpectedly +#define INVALID_FUNC_ERR 1 // An invalid function name was encountered +#define INVALID_NODE_ERR 2 // A node was not added due to parse error(s) +#define MODIFIED_FUNC_ERR 3 // A function is now different than the one read in +#define INVALID_MSGID_ERR 4 // An invalid message ID was encountered + +// Custom Script Block Lines +#define CUSTOM_SCRIPT_BLOCK_START_TAG "/**{CUSTOM_SCRIPT_BLOCK_START}** DO NOT EDIT! **/" +#define CUSTOM_SCRIPT_BLOCK_END_TAG "/**{CUSTOM_SCRIPT_BLOCK_END}**** DO NOT EDIT! **/" + + +///////////////////////////////////////////////////////////////////////////// +// Floating Menu Command Ranges +///////////////////////////////////////////////////////////////////////////// +// IMPORTANT NOTE: +// +// When adding a new command to the following menu system, it is vital +// that you tack on the number of ID's used to the following section's +// STARTING_COMMAND_ID!!!! +// +// This was done due to the compiler's limit on enclosing parentheses +///////////////////////////////////////////////////////////////////////////// + +// Define maximum ranges of values for the different lists +#define MAX_NAMED_OBJECTS 1000 +#define MAX_NAMED_TRIGGERS 100 +#define MAX_NAMED_DOORS 500 +#define MAX_NAMED_ROOMS 500 +#define MAX_NAMED_SCRIPTS 500 +#define MAX_NAMED_SOUNDS 700 +#define MAX_NAMED_TEXTURES 500 +#define MAX_NAMED_PATHS 250 +#define MAX_NAMED_MATCENS 250 +#define MAX_NAMED_GOALS 250 +#define MAX_NAMED_STRM_AUDIO 700 +#define MAX_SPECNAMES 300 + +// Define command ID starting point +#define STARTING_COMMAND_ID (WM_USER+10000) + +// Define external DALLAS commands +#define WM_HIGHLIGHT_SCRIPTS STARTING_COMMAND_ID +#define WM_ADD_SCRIPT (WM_HIGHLIGHT_SCRIPTS+1) +#define WM_ADD_SCRIPT_AND_HIGHLIGHT (WM_ADD_SCRIPT+1) + +// Define universal CANCEL command +#define CANCEL_COMMAND_ID (WM_ADD_SCRIPT_AND_HIGHLIGHT+1) + +// Define the command ID range for a "Assign" operation +#define ASSIGN_STARTING_COMMAND_ID (STARTING_COMMAND_ID+4) +#define ASSIGN_COMMAND_RANGE_START ASSIGN_STARTING_COMMAND_ID +#define ASSIGN_SCRIPT_ID_RANGE_START ASSIGN_COMMAND_RANGE_START +#define ASSIGN_SCRIPT_ID_RANGE_END (ASSIGN_SCRIPT_ID_RANGE_START+MAX_NAMED_SCRIPTS) +#define ASSIGN_EXEC_TIME_ID_RANGE_START (ASSIGN_SCRIPT_ID_RANGE_END+1) +#define ASSIGN_EXEC_TIME_ID_RANGE_END (ASSIGN_EXEC_TIME_ID_RANGE_START+MAX_EXEC_TIME_OPTIONS) +#define ASSIGN_CHAIN_ID_RANGE_START (ASSIGN_EXEC_TIME_ID_RANGE_END+1) +#define ASSIGN_CHAIN_ID_RANGE_END (ASSIGN_CHAIN_ID_RANGE_START+MAX_CHAIN_OPTIONS) +#define ASSIGN_SPECIFIC_VALUE_ID (ASSIGN_CHAIN_ID_RANGE_END+1) +#define ASSIGN_TRUE_ID (ASSIGN_SPECIFIC_VALUE_ID+1) +#define ASSIGN_FALSE_ID (ASSIGN_TRUE_ID+1) +#define ASSIGN_MESSAGE_ID_RANGE_START (ASSIGN_FALSE_ID+1) +#define ASSIGN_MESSAGE_ID_RANGE_END (ASSIGN_MESSAGE_ID_RANGE_START+MAX_MESSAGE_LIST_ENTRIES) +#define ASSIGN_EVENT_ID_RANGE_START (ASSIGN_MESSAGE_ID_RANGE_END+1) +#define ASSIGN_EVENT_ID_RANGE_END (ASSIGN_EVENT_ID_RANGE_START+MAX_EVENT_TYPES) +#define ASSIGN_LEVEL_ID (ASSIGN_EVENT_ID_RANGE_END+1) +#define ASSIGN_TRIGGER_ID_RANGE_START (ASSIGN_LEVEL_ID+1) +#define ASSIGN_TRIGGER_ID_RANGE_END (ASSIGN_TRIGGER_ID_RANGE_START+MAX_NAMED_TRIGGERS) +#define ASSIGN_OBJECT_ME_ID (ASSIGN_TRIGGER_ID_RANGE_END+1) +#define ASSIGN_OBJECT_IT_ID (ASSIGN_OBJECT_ME_ID+1) +#define ASSIGN_OBJECT_NONE_ID (ASSIGN_OBJECT_IT_ID+1) +#define ASSIGN_OBJECT_ID_RANGE_START (ASSIGN_OBJECT_NONE_ID+1) +#define ASSIGN_OBJECT_ID_RANGE_END (ASSIGN_OBJECT_ID_RANGE_START+MAX_NAMED_OBJECTS) +#define ASSIGN_ROOM_ID_RANGE_START (ASSIGN_OBJECT_ID_RANGE_END+1) +#define ASSIGN_ROOM_ID_RANGE_END (ASSIGN_ROOM_ID_RANGE_START+MAX_NAMED_ROOMS) +#define ASSIGN_EXPOP_ID_RANGE_START (ASSIGN_ROOM_ID_RANGE_END+1) +#define ASSIGN_EXPOP_ID_RANGE_END (ASSIGN_EXPOP_ID_RANGE_START+MAX_EXPRESSION_OPERATORS) +#define ASSIGN_ENUM_GOAL_ID (ASSIGN_EXPOP_ID_RANGE_END+1) +#define ASSIGN_ENUM_TIMER_ID (ASSIGN_ENUM_GOAL_ID+1) +#define ASSIGN_ENUM_MATCEN_ID (ASSIGN_ENUM_TIMER_ID+1) +#define ASSIGN_ENUM_VALUE_ID_RANGE_START (ASSIGN_ENUM_MATCEN_ID+1) +#define ASSIGN_ENUM_VALUE_ID_RANGE_END (ASSIGN_ENUM_VALUE_ID_RANGE_START+MAX_ENUM_VALUES) +#define ASSIGN_PATH_ID_RANGE_START (ASSIGN_ENUM_VALUE_ID_RANGE_END+1) +#define ASSIGN_PATH_ID_RANGE_END (ASSIGN_PATH_ID_RANGE_START+MAX_NAMED_PATHS) +#define ASSIGN_MATCEN_EVENT_ID (ASSIGN_PATH_ID_RANGE_END+1) +#define ASSIGN_MATCEN_ID_RANGE_START (ASSIGN_MATCEN_EVENT_ID+1) +#define ASSIGN_MATCEN_ID_RANGE_END (ASSIGN_MATCEN_ID_RANGE_START+MAX_NAMED_MATCENS) +#define ASSIGN_LEVEL_GOAL_ID (ASSIGN_MATCEN_ID_RANGE_END+1) +#define ASSIGN_LEVEL_GOAL_ID_RANGE_START (ASSIGN_LEVEL_GOAL_ID+1) +#define ASSIGN_LEVEL_GOAL_ID_RANGE_END (ASSIGN_LEVEL_GOAL_ID_RANGE_START+MAX_NAMED_GOALS) +#define ASSIGN_COMMAND_RANGE_END (ASSIGN_LEVEL_GOAL_ID_RANGE_END+1) + +// Define all command ID range for an "Add" (also serves as "Insert") operation +#define ADD_STARTING_COMMAND_ID (ASSIGN_STARTING_COMMAND_ID+MAX_NAMED_SCRIPTS+MAX_EXEC_TIME_OPTIONS+MAX_CHAIN_OPTIONS+MAX_MESSAGE_LIST_ENTRIES+MAX_EVENT_TYPES+MAX_NAMED_TRIGGERS+MAX_NAMED_OBJECTS+MAX_NAMED_ROOMS+MAX_EXPRESSION_OPERATORS+MAX_ENUM_VALUES+MAX_NAMED_PATHS+MAX_NAMED_MATCENS+MAX_NAMED_GOALS+26) +#define ADD_COMMAND_RANGE_START ADD_STARTING_COMMAND_ID +#define ADD_IF_THEN_CLAUSE_ID ADD_COMMAND_RANGE_START +#define ADD_ELSE_CLAUSE_ID (ADD_IF_THEN_CLAUSE_ID+1) +#define ADD_IF_THEN_ELSE_CLAUSE_ID (ADD_ELSE_CLAUSE_ID+1) +#define ADD_DO_NOTHING_ACTION_ID (ADD_IF_THEN_ELSE_CLAUSE_ID+1) +#define ADD_ACTION_ID_RANGE_START (ADD_DO_NOTHING_ACTION_ID+1) +#define ADD_ACTION_ID_RANGE_END (ADD_ACTION_ID_RANGE_START+MAX_ACTIONS) +#define ADD_LOGOP_ID_RANGE_START (ADD_ACTION_ID_RANGE_END+1) +#define ADD_LOGOP_ID_RANGE_END (ADD_LOGOP_ID_RANGE_START+MAX_LOGICAL_OPERATORS) +#define INSERT_LOGOP_ID_RANGE_START (ADD_LOGOP_ID_RANGE_END+1) +#define INSERT_LOGOP_ID_RANGE_END (INSERT_LOGOP_ID_RANGE_START+MAX_LOGICAL_OPERATORS) +#define ADD_CONDITION_ID_RANGE_START (INSERT_LOGOP_ID_RANGE_END+1) +#define ADD_CONDITION_ID_RANGE_END (ADD_CONDITION_ID_RANGE_START+MAX_CONDITION_TYPES) +#define ADD_COND_QBIN_ID_RANGE_START (ADD_CONDITION_ID_RANGE_END+1) +#define ADD_COND_QBIN_ID_RANGE_END (ADD_COND_QBIN_ID_RANGE_START+MAX_QUERIES) +#define ADD_COND_QCOMP_ID_RANGE_START (ADD_COND_QBIN_ID_RANGE_END+1) +#define ADD_COND_QCOMP_ID_RANGE_END (ADD_COND_QCOMP_ID_RANGE_START+MAX_QUERIES) +#define ADD_COMMAND_RANGE_END (ADD_COND_QCOMP_ID_RANGE_END+1) + +// Define all command ID range for a "Replace" operation +#define REPLACE_STARTING_COMMAND_ID (ADD_STARTING_COMMAND_ID+MAX_ACTIONS+MAX_LOGICAL_OPERATORS+MAX_LOGICAL_OPERATORS+MAX_CONDITION_TYPES+MAX_QUERIES+MAX_QUERIES+11) +#define REPLACE_COMMAND_RANGE_START REPLACE_STARTING_COMMAND_ID +#define REPLACE_QUERY_ID_RANGE_START REPLACE_COMMAND_RANGE_START +#define REPLACE_QUERY_ID_RANGE_END (REPLACE_QUERY_ID_RANGE_START+MAX_QUERIES) +#define REPLACE_LITERAL_ID_RANGE_START (REPLACE_QUERY_ID_RANGE_END+1) +#define REPLACE_LITERAL_ID_RANGE_END (REPLACE_LITERAL_ID_RANGE_START+MAX_LITERALS) +#define REPLACE_LIT_ENUM_ID_RANGE_START (REPLACE_LITERAL_ID_RANGE_END+1) +#define REPLACE_LIT_ENUM_ID_RANGE_END (REPLACE_LIT_ENUM_ID_RANGE_START+MAX_ENUMS) +#define REPLACE_LIT_FLAG_ID_RANGE_START (REPLACE_LIT_ENUM_ID_RANGE_END+1) +#define REPLACE_LIT_FLAG_ID_RANGE_END (REPLACE_LIT_FLAG_ID_RANGE_START+MAX_FLAGS) +#define REPLACE_DO_NOTHING_ACTION_ID (REPLACE_LIT_FLAG_ID_RANGE_END+1) +#define REPLACE_ACTION_ID_RANGE_START (REPLACE_DO_NOTHING_ACTION_ID+1) +#define REPLACE_ACTION_ID_RANGE_END (REPLACE_ACTION_ID_RANGE_START+MAX_ACTIONS) +#define REPLACE_LOGOP_ID_RANGE_START (REPLACE_ACTION_ID_RANGE_END+1) +#define REPLACE_LOGOP_ID_RANGE_END (REPLACE_LOGOP_ID_RANGE_START+MAX_LOGICAL_OPERATORS) +#define REPLACE_CONDITION_ID_RANGE_START (REPLACE_LOGOP_ID_RANGE_END+1) +#define REPLACE_CONDITION_ID_RANGE_END (REPLACE_CONDITION_ID_RANGE_START+MAX_CONDITION_TYPES) +#define REPLACE_COND_QBIN_ID_RANGE_START (REPLACE_CONDITION_ID_RANGE_END+1) +#define REPLACE_COND_QBIN_ID_RANGE_END (REPLACE_COND_QBIN_ID_RANGE_START+MAX_QUERIES) +#define REPLACE_COND_QCOMP_ID_RANGE_START (REPLACE_COND_QBIN_ID_RANGE_END+1) +#define REPLACE_COND_QCOMP_ID_RANGE_END (REPLACE_COND_QCOMP_ID_RANGE_START+MAX_QUERIES) +#define REPLACE_COMMAND_RANGE_END (REPLACE_COND_QCOMP_ID_RANGE_END+1) + +// Define all command ID range for a "Delete" operation +#define DELETE_STARTING_COMMAND_ID (REPLACE_STARTING_COMMAND_ID+MAX_QUERIES+MAX_LITERALS+MAX_ENUMS+MAX_FLAGS+MAX_ACTIONS+MAX_LOGICAL_OPERATORS+MAX_CONDITION_TYPES+MAX_QUERIES+MAX_QUERIES+11) +#define DELETE_COMMAND_RANGE_START DELETE_STARTING_COMMAND_ID +#define DELETE_ALL_ID DELETE_COMMAND_RANGE_START +#define DELETE_CHILDREN_ONLY_ID (DELETE_ALL_ID+1) +#define DELETE_COMMAND_RANGE_END (DELETE_CHILDREN_ONLY_ID+1) + + +///////////////////////////////////////////////////////////////////////////// +// CDallasMainDlg dialog +///////////////////////////////////////////////////////////////////////////// + +typedef char *char_ptr; + +class CDallasMainDlg : public CDialog +{ +private: + + // Storage for the Loaded script filename + CString m_ScriptFilename; + CString m_ScriptDLLFilename; + CString m_ScriptMessagesFilename; + CString m_DallasFunctionsFilename; + + // Modified variable storage + bool m_Modified; + + // Declare the image list for the tree control + CImageList m_TreeImageList; + + // Store the next message ID to be allocated + int m_NextScriptID; + + // The list of Message entries + tMessageListEntry *m_MessageEntryList[MAX_MESSAGE_LIST_ENTRIES]; + int m_MessageListErrorCode; + int m_NextMessageID; + + // The enumeration database + tEnumDBEntry m_EnumDatabase[MAX_ENUMS]; + int m_NumEnums; + + // The flag database + tFlagDBEntry m_FlagDatabase[MAX_FLAGS]; + int m_NumFlags; + + // The Action function database + char *m_FunctionCategories[MAX_CATEGORIES]; + tActionDBEntry m_ActionDatabase[MAX_ACTIONS]; + tQueryDBEntry m_QueryDatabase[MAX_QUERIES]; + int m_NumFunctionCategories; + int m_NumActions; + int m_NumQueries; + + // Storage for list of object handles (objects with custom names only) + int m_ObjectHandleList[MAX_NAMED_OBJECTS]; + int m_NumObjectHandles; + + // The list for organizing scripts into owner/event groups (prior to creating source) + tScriptOwnerGroup *m_ScriptGroupingList; + int m_NumScriptGroups; + + // Clipboard data + HTREEITEM m_ClipboardNode; + + // Custom Script Storage Data + char **m_CustomScriptLines; + int m_NumCustomScriptLines; + int m_MaxNumCustomScriptLines; + + // Name Lists + char *m_DoorList[MAX_NAMED_DOORS]; + int m_DoorListSize; + char *m_ObjectList[MAX_NAMED_OBJECTS]; + int m_ObjectListSize; + char *m_RoomList[MAX_NAMED_ROOMS]; + int m_RoomListSize; + char *m_TriggerList[MAX_NAMED_TRIGGERS]; + int m_TriggerListSize; + char *m_SoundList[MAX_NAMED_SOUNDS]; + int m_SoundListSize; + char *m_TextureList[MAX_NAMED_TEXTURES]; + int m_TextureListSize; + char *m_SpecnameList[MAX_SPECNAMES]; + int m_SpecnameListSize; + char *m_PathList[MAX_NAMED_PATHS]; + int m_PathListSize; + char *m_MatcenList[MAX_NAMED_MATCENS]; + int m_MatcenListSize; + char *m_GoalList[MAX_NAMED_GOALS]; + int m_GoalListSize; + char *m_StrmAudioList[MAX_NAMED_STRM_AUDIO]; + int m_StrmAudioListSize; + char *m_MessageNameList[MAX_MESSAGE_LIST_ENTRIES]; + int m_MessageNameListSize; + + // Drag and Drop Vars + CImageList* m_pDragImage; + BOOL m_bLDragging; + HTREEITEM m_hitemDrag,m_hitemDrop; + +public: + // Construction + CDallasMainDlg(CWnd* pParent = NULL); // standard constructor + + /////////////////////////////////// + // Public Interface Data + /////////////////////////////////// + int m_ScriptOwnerType; + int m_ScriptOwnerHandle; + + /////////////////////////////////// + // General Refresh functions + /////////////////////////////////// + void InitAll(void); + void ClearAll(void); + void LoadAll(void); + void SetAllFilenames(void); + void SetAllFilenamesToThis(char *level_path); + void Refresh(void); + + /////////////////////////////////// + // Manage System functions + /////////////////////////////////// + void CheckinScriptFiles(void); + void CheckoutScriptFiles(void); + void DeleteScriptFiles(void); + + /////////////////////////////////// + // Tree Control functions + /////////////////////////////////// + void InitTree(void); + void ClearTree(void); + + void UpdateTreeText(HTREEITEM parent); + + void UpdateNodeText(HTREEITEM node); + void UpdateAllParentNodesText(HTREEITEM node); + void FormatTreeText(CString &text, tTreeNodeData *data, HTREEITEM node=NULL); + void FormatConditionText(CString &text, HTREEITEM condition_node); + void FormatGenericExpressionText(CString &text, HTREEITEM gen_exp_node); + void FormatParameterValueText(CString &text, tTreeNodeData *data); + void FormatActionNodeText(CString &text, HTREEITEM action_node); + void FormatQueryNodeText(CString &text, HTREEITEM query_node); + + void SetBoldNodeText(HTREEITEM node, bool bold_on); + + void FreeTreeItem(HTREEITEM item); + void FreeTreeItemChildren(HTREEITEM item); + + void ExpandAll(HTREEITEM node, UINT nCode); // Works like CTreeCtrl::Expand(), except on child nodes as well + + HTREEITEM AddNodeToTree(HTREEITEM parent, HTREEITEM insertbefore, HTREEITEM src_node, bool expand=FALSE); + HTREEITEM AddNodeToTree(HTREEITEM parent, HTREEITEM insertbefore, tTreeNodeData *data_node, bool expand=FALSE); + + HTREEITEM CopyTree(HTREEITEM dest_parent, HTREEITEM dest_insert_before, HTREEITEM src_node); + HTREEITEM CopyChildren(HTREEITEM dest_parent, HTREEITEM src_parent); + + int ConvertParamCharToType(int param_char_ID); + int ConvertParamTypeToChar(int param_type); + + bool ParentIsComparisonConditional(HTREEITEM node); + int GetValidParamType(HTREEITEM node, CString &name); + int GetParamType(HTREEITEM node, CString &name); + + void SetTreeNodeImage(HTREEITEM node); // Sets the image for a node (based on node data) + + char *GetEventTypeString(int type); + char *GetEventCodeName(int type); + char *GetEventDataLine(int type); + void GetLogicalOperatorTypeString(int type, CString &string); + char *GetExpressionOperatorTypeString(int type); + char *GetExpressionOperatorCodeName(int type); + char *GetLiteralName(int type); + + bool ScriptHasAnIt(HTREEITEM script_node); + bool ScriptHasAMe(HTREEITEM script_node); + bool ScriptHasADoorMe(HTREEITEM script_node); + bool ScriptHasATimerID(HTREEITEM script_node); + bool ScriptHasAGoalID(HTREEITEM script_node); + bool ScriptHasAMatcenID(HTREEITEM script_node); + bool ScriptHasALevelGoalID(HTREEITEM script_node); + bool NodeIsIfClause(HTREEITEM node); + bool NodeIsClauseOfType(HTREEITEM node, int type); + bool CanAppendElseToNode(HTREEITEM node); + + int GetChildPosition(HTREEITEM child); + HTREEITEM GetNthChild(HTREEITEM parent, int n); + int GetChildCount(HTREEITEM parent); + int GetScriptID(HTREEITEM script_node); + HTREEITEM FindScriptIDNode(int scriptID); + int GetLowestUnusedScriptID(void); + int GetNodeType(HTREEITEM node); + int GetScriptOwnerType(HTREEITEM script_node); + int GetScriptEventType(HTREEITEM script_node); + bool SetScriptEventType(HTREEITEM script_node, int type); + + HTREEITEM GetParentNodeOfType(HTREEITEM child_node, int node_type); + HTREEITEM GetParameterParentNode(HTREEITEM param_node); + HTREEITEM GetScriptOwnerNode(HTREEITEM node); + HTREEITEM GetScriptEventNode(HTREEITEM node); + HTREEITEM GetConditionalHeaderNode(HTREEITEM node); + HTREEITEM GetActionHeaderNode(HTREEITEM node); + + tTreeNodeData *GetNearestFunctionNode(HTREEITEM node); + void DisplayFloatingPopupMenu(HTREEITEM node, POINT &pt); + int DeletePrompt(char *msg); + void ConfirmAfterDelete(HTREEITEM parent); + + void HighlightAllScripts(void); // Highlights scripts according to public owner data + void HighlightScript(HTREEITEM node); // Highlights a given script according to public owner data + + int ModifiedPrompt(void); // Displays the "are you sure?" dialog + void SetModified(bool value); + void SetTitleBar(void); + + /////////////////////////////////// + // Message List functions + /////////////////////////////////// + void InitMessageList(void); // initializes the message list + void ClearMessageList(void); // clears the message list + bool AddToMessageList(char *name, char *message); // adds a message to the list + char *FindMessageInList(char *name); // returns a message matching given name + int DeleteMessageListEntry(char *name); // Deletes a message entry + tMessageListEntry *GetEmptyMessageListEntry(void); // returns an available entry slot + + /////////////////////////////////////// + // Name List functions + /////////////////////////////////////// + void InitNameLists(void); + void ClearNameLists(void); + int FillNameListsFromTree(HTREEITEM parent, bool show_notspec_warnings); + int AddNameToListFromTreeNode(HTREEITEM node, bool show_notspec_warnings); + + // Funcs for displaying Indexed value messages + void InvSpecParamMsg(int scriptID, char *type_name); + void IndValNotSpecMsg(int scriptID, char *type_name); + void InvIndValMsg(int scriptID, char *type_name, int index, char *name); + int InvIndValPrompt(int scriptID, char *type_name, int index, char *name, int new_index); + void InvNameIndValMsg(int scriptID, char *type_name, int index, char *name, char *new_name); + int InvNameIndValPrompt(int scriptID, char *type_name, int index, char *name, char *new_name, int new_index); + + // Funcs for displaying object messages + void InvObjMsg(int scriptID, int handle, char *name); + int InvObjPrompt(int scriptID, int handle, char *name, int new_handle); + void InvNameObjMsg(int scriptID, int handle, char *name, char *new_name); + int InvNameObjPrompt(int scriptID, int handle, char *name, char *new_name, int new_handle); + + // Add/Find funcs for the individual name lists + int AddDoorToList(char *name); + int FindDoorInList(char *name); + + int AddObjectToList(char *name); + int FindObjectInList(char *name); + + int AddRoomToList(char *name); + int FindRoomInList(char *name); + + int AddTriggerToList(char *name); + int FindTriggerInList(char *name); + + int AddSoundToList(char *name); + int FindSoundInList(char *name); + + int AddTextureToList(char *name); + int FindTextureInList(char *name); + + int AddSpecnameToList(char *name); + int FindSpecnameInList(char *name); + + int AddPathToList(char *name); + int FindPathInList(char *name); + + int AddMatcenToList(char *name); + int FindMatcenInList(char *name); + + int AddGoalToList(char *name); + int FindGoalInList(char *name); + + int AddStrmAudioToList(char *name); + int FindStrmAudioInList(char *name); + + int AddMessageNameToList(char *name); + int FindMessageNameInList(char *name); + + /////////////////////////////////////// + // User Type Workshop Functions + /////////////////////////////////////// + int FillUserTypeBox(CComboBox *box); + int FillValuesBox(CListBox *box, char *utype_name); + int AddUserTypeValue(char *utype_name, char *value_name); + int DeleteUserTypeValue(char *utype_name, char *value_name); + int ChangeValueName(char *utype_name, char *old_name, char *new_name); + + /////////////////////////////////////// + // Enum Database functions + /////////////////////////////////////// + void InitEnumDatabase(void); // Initializes the enum DB for use + void ClearEnumDatabase(void); // Clears any allocated data for the enums + int GetEnumID(char *name); // Returns the DB slot matching the given enum type name + char *GetEnumValueName(char *name, int value); // Returns the name bound to an enum value + + bool GetEnumValue(char *name, char *value_name, int &value); // obtains value for given value name + + int FillEnumTypesMenu(CMenu *enum_menu, int command_offset, char *valid_name); + int FillEnumValuesMenu(CMenu *enum_menu, int command_offset, char *enum_name); + + /////////////////////////////////////// + // Flag Database functions + /////////////////////////////////////// + void InitFlagDatabase(void); // Initializes the flag DB for use + void ClearFlagDatabase(void); // Clears any allocated data for the flags + int GetFlagID(char *name); // Returns the DB slot matching the given flag type name + char *GetFlagValueName(char *name, int value); // Returns the name bound to an flag value + + + bool FormatFlagValueNames(char *name, int value, CString &text); // Returns the name bound to an flag value + bool GetFlagValue(char *name, char *value_name, int &value); // obtains value for given value name + + int FillFlagTypesMenu(CMenu *flag_menu, int command_offset, char *valid_name); + int FillFlagValuesBox(CCheckListBox *box, char *flag_name, int flags_value, int valid_flags_mask); + + /////////////////////////////////////// + // Action and Query Database functions + /////////////////////////////////////// + void InitFunctionDatabases(void); // Initialize the Action and Query Database Arrays + void ClearFunctionDatabases(void); // Frees up any allocated memory + void ParseFunctionFile(char *filename, bool show_errors=TRUE); // Parses a file, and adds any Actions and Querys to the database + char *GetActionDesc(int ID); // Returns the Action description + char *GetActionHelp(int ID); // Returns the Action help text + char *GetActionFunc(int ID); // Returns the Action function name + int GetActionFuncID(char *func_name); // Searches action list for action matching given function name + char *GetQueryDesc(int ID); // Returns the Query description + char *GetQueryHelp(int ID); // Returns the Query help text + char *GetQueryFunc(int ID); // Returns the Query function name + int GetQueryFuncID(char *func_name); // Searches query list for query matching given function name + int GetQueryReturnType(int ID, CString &name); // Returns the Query's return type (parameter type) + int GetFunctionCategoryID(char *catname); // Matches an integer ID to a given category name + + void FunctionFileParseError(int error_code, int linenum, char *filename); // Handle Parse Errors + void ParseOutActionVarTypes(char *new_desc, char *old_desc); // Returns a description copy with the parameter type info removed + void ParseOutQueryVarTypes(char *new_desc, char *old_desc); // Returns a description copy with the parameter type info removed + bool ValidateActionNode(HTREEITEM node, int linenum); + bool ValidateQueryNode(HTREEITEM node, int linenum); + void FillActionMenu(CMenu *action_menu, int command_offset); + void FillQueryMenu(CMenu *query_menu, int command_offset, int valid_return_type, char *valid_return_name); + bool ConformParamNode(HTREEITEM parent_node, HTREEITEM ¶m_node, int type, char *name, char *def_value=NULL); + + int ParseNthParam(HTREEITEM func_node, int n, CString &name_text, CString &default_text, CString &range_text); + int ParseNthParam(char *desc, int n, CString &name_text, CString &default_text, CString &range_text); + int ParseParamBlock(char_ptr &line, CString &name_text, CString &default_text, CString &range_text); + + bool VerifyIntegerRange(int value, char *range_desc); + bool VerifyFloatRange(float value, char *range_desc); + + /////////////////////////////////// + // Script Grouping List functions + /////////////////////////////////// + void InitScriptGroupingList(void); + void ClearScriptGroupingList(void); + int AddNodeToScriptOwnerGroup(int pos, HTREEITEM script_node); + int AddNodeToScriptGroupingList(HTREEITEM script_node); + int BuildScriptGroupingList(void); + + char *CreateScriptConstantName(int pos); + char *CreateScriptClassName(int pos); + char *CreateScriptGlobalCtrName(int ID); + + /////////////////////////////////// + // Source File Parsing Functions + /////////////////////////////////// + int ParseSourceScript(char *filename); // does high-level parsing of CPP file + int ParseMsgTableFile(char *filename); // reads in the message list from a file + + HTREEITEM ParseScriptNodeLine_v0(char *line, int linenum, HTREEITEM parent, bool &skip_all_children, HTREEITEM insert_before=TVI_LAST); + HTREEITEM ParseScriptNodeLine_v1U(char *line, int linenum, HTREEITEM parent, bool &skip_all_children, int version, HTREEITEM insert_before=TVI_LAST); + void ScriptFileParseError(int error_code, int linenum, int script_ID, char *name); + void SpecialScriptFileParseError(int linenum, int script_ID, char *type_name, char *name); + bool ValidateFunctionNode(HTREEITEM node, int linenum); + + /////////////////////////////////// + // Custom Script Block Functions + /////////////////////////////////// + void InitCustomScriptStorage(void); + void ClearCustomScriptStorage(void); + int CountCustomScriptLines(CFILE *infile); + int ParseCustomScriptFile(char *filename, bool show_errors=TRUE); + void WriteCustomScriptBlock(void); + + /////////////////////////////////// + // Source File Creation Functions + /////////////////////////////////// + int CreateMsgTableFile(char *filename); // writes message list to file + void TabOver(void); // writes series of tabs + int CreateScriptFile(char *filename); // creates the new script file + void CreateLevelEventCases(tScriptOwnerGroup *owner_group); + void CreateEventCases(tScriptOwnerGroup *owner_group); // writes the valid event cases + void WriteScriptCode(HTREEITEM script_node); // writes script code for a script node + void WriteConditionalCodeBlock(HTREEITEM conditional_header_node); // writes a conditional block segment + void WriteLogicalOpExpression(HTREEITEM logop_node); // writes out a logical operation block + void WriteConditionalStatement(HTREEITEM condition_node); // writes out a conditional statement + void WriteQueryFunctionCall(HTREEITEM query_node); // writes out query function call + void WriteActionCodeBlock(HTREEITEM action_header_node); // writes an action block segment + void WriteActionFunctionCall(HTREEITEM action_node); // writes out action function call + void WriteFunctionParameter(HTREEITEM param_node); // writes out a parameter + void WriteScriptSaveBlock(void); // creates the tree block (for saving scripts) + void WriteScriptTreeDump(void); + void WriteUserTypeVals(void); + void WriteNameLists(void); + void WriteNameListArrays(void); + void WriteNameArrayLookupCode(void); + void WriteScriptChildrenDump(HTREEITEM parent, bool filter_on=FALSE); + void WriteScriptNodeDump_v0(HTREEITEM parent); + void WriteScriptNodeDump_v1U(HTREEITEM parent, bool filter_on=FALSE); + + /////////////////////////////////// + // Object Handle List Functions + /////////////////////////////////// + void InitObjectHandleList(void); + void ClearObjectHandleList(void); + int AddToObjectHandleList(int handle); + + /////////////////////////////////// + // Floating Menu Creation Functions + /////////////////////////////////// + void FillObjectMenu(CMenu *object_menu, int command_offset, bool show_other); + int FillObjectTypeMenu(CMenu *object_menu, int command_offset, int obj_type); + int FillRoomMenu(CMenu *room_menu, int command_offset); + int FillSoundsMenu(CMenu *sound_menu, int command_offset); + int FillTriggerMenu(CMenu *trigger_menu, int command_offset); + int FillPathMenu(CMenu *path_menu, int command_offset); + int FillMatcenMenu(CMenu *matcen_menu, int command_offset); + int FillLevelGoalMenu(CMenu *level_goal_menu, int command_offset); + int FillScriptMenu(CMenu *script_menu, int command_offset); + int FillLogOpMenu(CMenu *log_op_menu, int command_offset); + int FillExpOpMenu(CMenu *exp_op_menu, int command_offset, int op_type); + void FillConditionMenu(CMenu *condition_menu, int command_offset); + int FillLiteralMenu(CMenu *literal_menu, int command_offset, int enum_command_offset, int flag_command_offset, int valid_type, char *valid_name); + + void DisplayScriptHeaderNodeMenu(POINT *point); + void DisplayScriptOwnerNodeMenu(POINT *point); + void DisplayScriptEventNodeMenu(POINT *point, int owner_type, bool has_a_door_me); + void DisplayLogicalOperatorNodeMenu(POINT *point); + void DisplayConditionalStatementNodeMenu(POINT *point); + void DisplayExpressionNodeMenu(POINT *point, int valid_return_type, char *valid_return_name); + void DisplayExpressionOperatorNodeMenu(POINT *point, int op_type); + void DisplayActionStatementNodeMenu(POINT *point); + void DisplayActionHeaderNodeMenu(POINT *point, int level_type, int clause_type, bool can_add_else); + void DisplayParameterNodeMenu(POINT *point, int param_type, char *param_name, int valid_return_type, char *valid_return_name, bool has_an_it, bool has_a_me, bool has_a_door_me, bool has_a_goalID, bool has_a_timerID, bool has_a_matcenID, bool has_a_levgoalID); + + void ColumnizePopupMenu(CMenu *menu); + + /////////////////////////////////// + // Functions to Assign Values + /////////////////////////////////// + void AssignScriptID(int pos); + void AssignExecTime(int ID); + void AssignChainOption(int ID); + void AssignSpecificValue(void); + void AssignNamedValue(int type, int handle); + void AssignEventType(int type); + void AssignBooleanValue(int type); + void AssignMessageName(int msg_ID); + void AssignExpOpType(int type); + void AssignEnumValueType(int type); + + /////////////////////////////////// + // Functions to Add Tree Nodes + /////////////////////////////////// + void AddNestedIfThenClause(void); + void AddNestedElseClause(void); + void AddNestedIfThenElseClause(void); + void AddConditionalStatementNode(int type, int query_id=-1); + void AddActionStatementNode(int action_ID); + void AddActionParameterNodes(HTREEITEM action_node); + void AddQueryParameterNodes(HTREEITEM query_node); + void AddLogicalOperatorNode(int type); + void InsertLogicalOperatorNode(int type); + + /////////////////////////////////// + // Functions to Replace Tree Nodes + /////////////////////////////////// + void ReplaceWithQueryNode(int query_ID); + void ReplaceWithLiteralNode(int literal_type, int index); + void DoComparisonMatchup(HTREEITEM node); + void ReplaceWithActionNode(int action_ID); + void ReplaceWithLogOpNode(int type); + void ReplaceWithConditionNode(int type, int query_id=-1); + + /////////////////////////////////// + // Functions to Add Default Trees + /////////////////////////////////// + HTREEITEM CreateDefaultScriptTree(int script_ID, HTREEITEM insert_before=NULL); + HTREEITEM CreateDefaultIfThenClause(HTREEITEM parent, HTREEITEM insert_before, int type); + HTREEITEM CreateDefaultElseClause(HTREEITEM parent, HTREEITEM insert_before); + HTREEITEM CreateDefaultConditionalStatementNode(HTREEITEM parent); + HTREEITEM CreateDefaultConditionalStatementSubtree(HTREEITEM parent, int type, int query_id=-1); + HTREEITEM CreateDefaultExpressionOperatorNode(HTREEITEM parent, int type); + HTREEITEM CreateDefaultActionStatementNode(HTREEITEM parent); + HTREEITEM CreateDefaultParameterNode(HTREEITEM parent, HTREEITEM insert_before, int param_type, char *name, char *def_value=NULL); + HTREEITEM CreateDefaultClipboardNode(void); + + /////////////////////////////////// + // Functions to Handle Copy/Paste + /////////////////////////////////// + void PerformScriptCopy(void); + void PerformActionCopy(HTREEITEM action_node); + void PerformConditionalCopy(HTREEITEM conditional_node); + void PerformLogOpCopy(HTREEITEM logop_node); + void PerformClauseCopy(HTREEITEM clause_node); + + void PerformScriptPaste(void); + void PerformActionPaste(HTREEITEM src_action_node); + void PerformConditionalPaste(HTREEITEM src_conditional_node); + void PerformLogOpPaste(HTREEITEM src_logop_node); + void PerformClausePaste(HTREEITEM src_clause_node); + + bool NodeIsInClipboard(HTREEITEM node); + + /////////////////////////////////////////////// + // Functions to search tree and replace values + /////////////////////////////////////////////// + int UpdateStringParams(HTREEITEM root, char *old_name, char *new_name); + + /////////////////////////////////////////// + // Functions to Handle Script Drag-n-Drop + /////////////////////////////////////////// + bool IsDropSource(HTREEITEM item); + HTREEITEM GetDropTarget(HTREEITEM item); + + /////////////////////////////////////////// + // Functions to Handle Highlight Interface + /////////////////////////////////////////// + void ClearHighlightRadioButtons(void); + void FillHighlightEventList(void); + int GetHighlightedEvent(void); + void SetHighlightedEvent(int type); + + ///////////////////////////////////// + // Functions to Handle Import/Export + ///////////////////////////////////// + bool ScriptLibraryFilePrompt(CString &filename, bool use_import_msg); + bool ImportScriptFromFile(char *filename, char *script_name); + bool ExportScriptToFile(char *filename, char *script_name); + + +// Dialog Data + //{{AFX_DATA(CDallasMainDlg) + enum { IDD = IDD_DALLAS_MAIN_DIALOG }; + CComboBox m_EventList; + CTreeCtrl m_ScriptTree; + CEdit m_HelpEdit; + CListBox m_MessageList; + CEdit m_MessageEdit; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDallasMainDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDallasMainDlg) + afx_msg void OnNewMessageButton(); + afx_msg void OnDeleteMessageButton(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeMessageList(); + afx_msg void OnChangeMessageEdit(); + afx_msg void OnDblclkMessageList(); + afx_msg void OnChangeMessageNameButton(); + virtual void OnOK(); + afx_msg void OnClose(); + afx_msg void OnDestroy(); + virtual void OnCancel(); + afx_msg void OnNewScriptButton(); + afx_msg void OnInsertScriptButton(); + afx_msg void OnDeleteScriptButton(); + afx_msg void OnRclickEventTree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDblclkScriptTree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnSelchangedScriptTree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnSaveButton(); + afx_msg void OnKeydownEventTree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnCopyButton(); + afx_msg void OnPasteButton(); + afx_msg void OnHighlightButton(); + afx_msg void OnExpandAllButton(); + afx_msg void OnCollapseAllButton(); + afx_msg void OnUtypesButton(); + afx_msg void OnBegindragEventTree(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnAllobjRadio(); + afx_msg void OnAlltrigRadio(); + afx_msg void OnNoneRadio(); + afx_msg void OnSpecificRadio(); + afx_msg void OnLevelRadio(); + afx_msg void OnImportButton(); + afx_msg void OnExportButton(); + afx_msg void OnEventRadio(); + afx_msg void OnSelchangeEventCombo(); + //}}AFX_MSG + afx_msg void OnActivate( UINT nState, CWnd* pWndOther, BOOL bMinimized ); + afx_msg LONG OnHighlightScripts(UINT, LONG); + afx_msg LONG OnAddScript(UINT, LONG); + afx_msg LONG OnAddScriptAndHighlight(UINT, LONG); + afx_msg void OnMenuSelectionOfTypeAssign(UINT nID); + afx_msg void OnMenuSelectionOfTypeAdd(UINT nID); + afx_msg void OnMenuSelectionOfTypeReplace(UINT nID); + afx_msg void OnMenuSelectionOfTypeDelete(UINT nID); + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DALLASMAINDLG_H__93285122_90E1_11D2_A4E0_00A0C96ED60D__INCLUDED_) diff --git a/editor/DallasSoundDlg.cpp b/editor/DallasSoundDlg.cpp new file mode 100644 index 00000000..c1ccd304 --- /dev/null +++ b/editor/DallasSoundDlg.cpp @@ -0,0 +1,125 @@ +// DallasSoundDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "hlsoundlib.h" +#include "soundload.h" +#include "DallasSoundDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDallasSoundDlg dialog + + +CDallasSoundDlg::CDallasSoundDlg(CWnd* pParent /*=NULL*/) + : CDialog(CDallasSoundDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDallasSoundDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + m_SoundName=""; + m_SoundIndex=-1; +} + + +void CDallasSoundDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDallasSoundDlg) + DDX_Control(pDX, IDC_SOUND_LIST, m_SoundList); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDallasSoundDlg, CDialog) + //{{AFX_MSG_MAP(CDallasSoundDlg) + ON_BN_CLICKED(IDC_PLAY_SOUND_BUTTON, OnPlaySoundButton) + ON_BN_CLICKED(IDC_STOP_SOUNDS_BUTTON, OnStopSoundsButton) + ON_LBN_DBLCLK(IDC_SOUND_LIST, OnDblclkSoundList) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDallasSoundDlg message handlers + +BOOL CDallasSoundDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + FillSoundList(); + + if(!m_SoundName.IsEmpty()) + m_SoundList.SelectString(-1,m_SoundName.GetBuffer(0)); + + Sound_system.BeginSoundFrame(FALSE); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CDallasSoundDlg::OnOK() +{ + int index=m_SoundList.GetCurSel(); + if(index==LB_ERR) return; + + m_SoundIndex=m_SoundList.GetItemData(index); + Sound_system.StopAllSounds(); + Sound_system.EndSoundFrame(); + + CDialog::OnOK(); +} + +void CDallasSoundDlg::OnCancel() +{ + Sound_system.StopAllSounds(); + Sound_system.EndSoundFrame(); + + CDialog::OnCancel(); +} + +void CDallasSoundDlg::OnPlaySoundButton() +{ + int index; + index=m_SoundList.GetCurSel(); + if(index==LB_ERR) return; + + CString sound_name; + m_SoundList.GetText(index,sound_name); + + Sound_system.BeginSoundFrame(FALSE); + Sound_system.Play2dSound(FindSoundName(sound_name.GetBuffer(0)),MAX_GAME_VOLUME); + Sound_system.EndSoundFrame(); +} + +void CDallasSoundDlg::OnStopSoundsButton() +{ + Sound_system.StopAllSounds(); +} + +void CDallasSoundDlg::FillSoundList(void) +{ + int i; + + // Fill the menus with sounds + for (i=0;i0)) { + int index; + index=m_SoundList.AddString(Sounds[i].name); + if(index!=LB_ERR) { + m_SoundList.SetItemData(index,i); + } + } + } +} + +void CDallasSoundDlg::OnDblclkSoundList() +{ + OnPlaySoundButton(); +} diff --git a/editor/DallasSoundDlg.h b/editor/DallasSoundDlg.h new file mode 100644 index 00000000..bb5df981 --- /dev/null +++ b/editor/DallasSoundDlg.h @@ -0,0 +1,58 @@ +#if !defined(AFX_DALLASSOUNDDLG_H__54A05001_AEE2_11D2_A4E0_00A0C96ED60D__INCLUDED_) +#define AFX_DALLASSOUNDDLG_H__54A05001_AEE2_11D2_A4E0_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DallasSoundDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDallasSoundDlg dialog + +class CDallasSoundDlg : public CDialog +{ +// Construction +public: + + CString m_SoundName; + int m_SoundIndex; + + + CDallasSoundDlg(CWnd* pParent = NULL); // standard constructor + + void FillSoundList(void); + +// Dialog Data + //{{AFX_DATA(CDallasSoundDlg) + enum { IDD = IDD_DALLAS_SOUND_DIALOG }; + CListBox m_SoundList; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDallasSoundDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDallasSoundDlg) + virtual void OnOK(); + virtual void OnCancel(); + afx_msg void OnPlaySoundButton(); + afx_msg void OnStopSoundsButton(); + virtual BOOL OnInitDialog(); + afx_msg void OnDblclkSoundList(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DALLASSOUNDDLG_H__54A05001_AEE2_11D2_A4E0_00A0C96ED60D__INCLUDED_) diff --git a/editor/DallasStrmAudioDlg.cpp b/editor/DallasStrmAudioDlg.cpp new file mode 100644 index 00000000..f9549bf0 --- /dev/null +++ b/editor/DallasStrmAudioDlg.cpp @@ -0,0 +1,108 @@ +// DallasStrmAudioDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "DallasUtilities.h" +#include "manage.h" +#include "streamaudio.h" +#include "DallasStrmAudioDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDallasStrmAudioDlg dialog + + +CDallasStrmAudioDlg::CDallasStrmAudioDlg(CWnd* pParent /*=NULL*/) + : CDialog(CDallasStrmAudioDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDallasStrmAudioDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_Filename=""; +} + + +void CDallasStrmAudioDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDallasStrmAudioDlg) + DDX_Control(pDX, IDC_STRM_AUDIO_LIST, m_StrmAudioBox); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDallasStrmAudioDlg, CDialog) + //{{AFX_MSG_MAP(CDallasStrmAudioDlg) + ON_LBN_DBLCLK(IDC_STRM_AUDIO_LIST, OnDblclkStrmAudioList) + ON_BN_CLICKED(IDC_PLAY_STRM_AUDIO_BUTTON, OnPlayStrmAudioButton) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDallasStrmAudioDlg message handlers + +void CDallasStrmAudioDlg::OnOK() +{ + // TODO: Add extra validation here + int index=m_StrmAudioBox.GetCurSel(); + if(index==LB_ERR) return; + + m_StrmAudioBox.GetText(index,m_Filename); + + CDialog::OnOK(); +} + +void CDallasStrmAudioDlg::OnCancel() +{ + // TODO: Add extra cleanup here + + CDialog::OnCancel(); +} + +BOOL CDallasStrmAudioDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + FillStrmAudioList(); + + if(!m_Filename.IsEmpty()) + m_StrmAudioBox.SelectString(-1,m_Filename.GetBuffer(0)); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CDallasStrmAudioDlg::OnDblclkStrmAudioList() +{ + CString filename; + + int index=m_StrmAudioBox.GetCurSel(); + if(index==LB_ERR) return; + + m_StrmAudioBox.GetText(index,filename); + StreamPlay(filename.GetBuffer(0),1,0); +} + +void CDallasStrmAudioDlg::OnPlayStrmAudioButton() +{ + OnDblclkStrmAudioList(); +} + +void CDallasStrmAudioDlg::FillStrmAudioList(void) +{ + bool file_found; + char filename[PAGENAME_LEN+1]; + + file_found=FindManageFirst(filename,"*.osf"); + while(file_found) { + m_StrmAudioBox.AddString(filename); + file_found=FindManageNext(filename); + } + FindManageClose(); +} diff --git a/editor/DallasStrmAudioDlg.h b/editor/DallasStrmAudioDlg.h new file mode 100644 index 00000000..2a373646 --- /dev/null +++ b/editor/DallasStrmAudioDlg.h @@ -0,0 +1,54 @@ +#if !defined(AFX_DALLASSTRMAUDIODLG_H__5D495B20_C7F1_11D2_A4E0_00A0C96ED60D__INCLUDED_) +#define AFX_DALLASSTRMAUDIODLG_H__5D495B20_C7F1_11D2_A4E0_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DallasStrmAudioDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDallasStrmAudioDlg dialog + +class CDallasStrmAudioDlg : public CDialog +{ +// Construction +public: + CString m_Filename; + + CDallasStrmAudioDlg(CWnd* pParent = NULL); // standard constructor + + void FillStrmAudioList(void); + +// Dialog Data + //{{AFX_DATA(CDallasStrmAudioDlg) + enum { IDD = IDD_DALLAS_STRM_AUDIO_DIALOG }; + CListBox m_StrmAudioBox; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDallasStrmAudioDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDallasStrmAudioDlg) + virtual void OnOK(); + virtual void OnCancel(); + virtual BOOL OnInitDialog(); + afx_msg void OnDblclkStrmAudioList(); + afx_msg void OnPlayStrmAudioButton(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DALLASSTRMAUDIODLG_H__5D495B20_C7F1_11D2_A4E0_00A0C96ED60D__INCLUDED_) diff --git a/editor/DallasTextureDlg.cpp b/editor/DallasTextureDlg.cpp new file mode 100644 index 00000000..dc80ebc5 --- /dev/null +++ b/editor/DallasTextureDlg.cpp @@ -0,0 +1,92 @@ +// DallasTextureDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "gametexture.h" +#include "DallasTextureDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDallasTextureDlg dialog + + +CDallasTextureDlg::CDallasTextureDlg(CWnd* pParent /*=NULL*/) + : CDialog(CDallasTextureDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDallasTextureDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + m_TextureName=""; + m_TextureIndex=-1; +} + + +void CDallasTextureDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDallasTextureDlg) + DDX_Control(pDX, IDC_TEXTURE_LIST, m_TextureList); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDallasTextureDlg, CDialog) + //{{AFX_MSG_MAP(CDallasTextureDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDallasTextureDlg message handlers + +BOOL CDallasTextureDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + FillTextureList(); + + if(!m_TextureName.IsEmpty()) + m_TextureList.SelectString(-1,m_TextureName.GetBuffer(0)); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CDallasTextureDlg::OnOK() +{ + int index=m_TextureList.GetCurSel(); + if(index==LB_ERR) return; + + m_TextureIndex=m_TextureList.GetItemData(index); + + CDialog::OnOK(); +} + +void CDallasTextureDlg::OnCancel() +{ + // TODO: Add extra cleanup here + + CDialog::OnCancel(); +} + +void CDallasTextureDlg::FillTextureList(void) +{ + int i; + + // Fill the menus with sounds + for (i=0;i0)) { + int index; + index=m_TextureList.AddString(GameTextures[i].name); + if(index!=LB_ERR) { + m_TextureList.SetItemData(index,i); + } + } + } +} diff --git a/editor/DallasTextureDlg.h b/editor/DallasTextureDlg.h new file mode 100644 index 00000000..d395e5f1 --- /dev/null +++ b/editor/DallasTextureDlg.h @@ -0,0 +1,54 @@ +#if !defined(AFX_DALLASTEXTUREDLG_H__68211402_B2C7_11D2_A4E0_00A0C96ED60D__INCLUDED_) +#define AFX_DALLASTEXTUREDLG_H__68211402_B2C7_11D2_A4E0_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DallasTextureDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDallasTextureDlg dialog + +class CDallasTextureDlg : public CDialog +{ +// Construction +public: + CString m_TextureName; + int m_TextureIndex; + + + CDallasTextureDlg(CWnd* pParent = NULL); // standard constructor + + void FillTextureList(void); + +// Dialog Data + //{{AFX_DATA(CDallasTextureDlg) + enum { IDD = IDD_DALLAS_TEXTURE_DIALOG }; + CListBox m_TextureList; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDallasTextureDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDallasTextureDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual void OnCancel(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DALLASTEXTUREDLG_H__68211402_B2C7_11D2_A4E0_00A0C96ED60D__INCLUDED_) diff --git a/editor/DallasUserTypesDlg.cpp b/editor/DallasUserTypesDlg.cpp new file mode 100644 index 00000000..f4e27979 --- /dev/null +++ b/editor/DallasUserTypesDlg.cpp @@ -0,0 +1,258 @@ +// DallasUserTypesDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "cfile.h" + +#ifdef NEWEDITOR +#include "NewEditor.h" +#else +#include "editor.h" +#endif + +#include "DallasMainDlg.h" +#include "DallasGenericPromptDlg.h" +#include "DallasUserTypesDlg.h" + +CDallasMainDlg *GetDallasDialogPtr(void); + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +CString last_type_selected; + +///////////////////////////////////////////////////////////////////////////// +// CDallasUserTypesDlg dialog + + +CDallasUserTypesDlg::CDallasUserTypesDlg(CWnd* pParent /*=NULL*/) + : CDialog(CDallasUserTypesDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDallasUserTypesDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CDallasUserTypesDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDallasUserTypesDlg) + DDX_Control(pDX, IDC_VALUES_LIST, m_ValuesListBox); + DDX_Control(pDX, IDC_UTYPE_COMBO, m_UserTypeCombo); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDallasUserTypesDlg, CDialog) + //{{AFX_MSG_MAP(CDallasUserTypesDlg) + ON_BN_CLICKED(IDC_ADD_BUTTON, OnAddButton) + ON_BN_CLICKED(IDC_CHANGE_BUTTON, OnChangeButton) + ON_BN_CLICKED(IDC_DELETE_BUTTON, OnDeleteButton) + ON_CBN_SELCHANGE(IDC_UTYPE_COMBO, OnSelchangeUtypeCombo) + ON_LBN_DBLCLK(IDC_VALUES_LIST, OnDblclkValuesList) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDallasUserTypesDlg message handlers + +BOOL CDallasUserTypesDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CDallasMainDlg *m_DallasModelessDlgPtr; + m_DallasModelessDlgPtr = GetDallasDialogPtr(); + + // If Dallas is up, fill in the user type and value boxes + if(m_DallasModelessDlgPtr!=NULL) { + m_DallasModelessDlgPtr->FillUserTypeBox(&m_UserTypeCombo); + + if(!last_type_selected.IsEmpty()) { + m_UserTypeCombo.SelectString(-1,last_type_selected.GetBuffer(0)); + } + + OnSelchangeUtypeCombo(); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CDallasUserTypesDlg::OnAddButton() +{ + CDallasGenericPromptDlg dlg; + int index; + CString name; + + CDallasMainDlg *m_DallasModelessDlgPtr; + m_DallasModelessDlgPtr = GetDallasDialogPtr(); + + if(m_DallasModelessDlgPtr==NULL) return; + + // Get the name of the user type + index=m_UserTypeCombo.GetCurSel(); + if(index==CB_ERR) return; + + m_UserTypeCombo.GetLBText(index,name); + if(name.IsEmpty()) return; + + // Display the prompt dialog + dlg.m_DialogTitle="Value Name Prompt"; + dlg.m_PromptText="Enter a name for the new value:"; + dlg.m_PromptData=""; + dlg.m_MaxDataLength=MAX_MESSAGE_NAME_LEN; + + if(dlg.DoModal()==IDCANCEL) return; + + // Check if the message name is valid + char *valname=dlg.m_PromptData.GetBuffer(0); + if(strlen(valname)==0) return; + for(unsigned int j=0;jGetEnumValue(name.GetBuffer(0),valname,pos)) { + MessageBox("That value name is already in use!\n\nYou must enter a UNIQUE name.","Invalid Value Name",MB_OK|MB_ICONEXCLAMATION); + return; + } + + // Add the value to the enum database + pos=m_DallasModelessDlgPtr->AddUserTypeValue(name.GetBuffer(0),valname); + if(pos==0) return; + if(pos==-1) { + MessageBox("The value could not be added.\n\nThe list may be full.","Value Not Added",MB_OK|MB_ICONEXCLAMATION); + return; + } + + // Add the value to the list + m_ValuesListBox.InsertString(pos-1,valname); +} + +void CDallasUserTypesDlg::OnChangeButton() +{ + CDallasGenericPromptDlg dlg; + int index; + CString type_name, value_name; + + CDallasMainDlg *m_DallasModelessDlgPtr; + m_DallasModelessDlgPtr = GetDallasDialogPtr(); + + if(m_DallasModelessDlgPtr==NULL) return; + + // Get the name of the user type + index=m_UserTypeCombo.GetCurSel(); + if(index==CB_ERR) return; + + m_UserTypeCombo.GetLBText(index,type_name); + if(type_name.IsEmpty()) return; + + // Get the name of the selected value + index=m_ValuesListBox.GetCurSel(); + if(index==LB_ERR) return; + + m_ValuesListBox.GetText(index,value_name); + if(value_name.IsEmpty()) return; + + // Display the prompt dialog + dlg.m_DialogTitle="Value Name Prompt"; + dlg.m_PromptText="Enter a new name for this value:"; + dlg.m_PromptData=value_name; + dlg.m_MaxDataLength=MAX_MESSAGE_NAME_LEN; + + if(dlg.DoModal()==IDCANCEL) return; + + // Check if the value name is valid + char *valname=dlg.m_PromptData.GetBuffer(0); + if(strlen(valname)==0) return; + for(unsigned int j=0;jGetEnumValue(type_name.GetBuffer(0),valname,pos) && strcmp(valname,value_name.GetBuffer(0))!=0) { + MessageBox("That value name is already in use!\n\nYou must enter a UNIQUE name.","Invalid Value Name",MB_OK|MB_ICONEXCLAMATION); + return; + } + + // Change the name of the value + if(m_DallasModelessDlgPtr->ChangeValueName(type_name.GetBuffer(0),value_name.GetBuffer(0),valname)) { + m_ValuesListBox.DeleteString(index); + m_ValuesListBox.InsertString(index,valname); + m_ValuesListBox.SetCurSel(index); + } +} + +void CDallasUserTypesDlg::OnDeleteButton() +{ + int index; + CString type_name, value_name; + + CDallasMainDlg *m_DallasModelessDlgPtr; + m_DallasModelessDlgPtr = GetDallasDialogPtr(); + + if(m_DallasModelessDlgPtr==NULL) return; + + // Get the name of the user type + index=m_UserTypeCombo.GetCurSel(); + if(index==CB_ERR) return; + + m_UserTypeCombo.GetLBText(index,type_name); + if(type_name.IsEmpty()) return; + + // Get the name of the selected value + index=m_ValuesListBox.GetCurSel(); + if(index==LB_ERR) return; + + m_ValuesListBox.GetText(index,value_name); + if(value_name.IsEmpty()) return; + + if(m_DallasModelessDlgPtr->DeleteUserTypeValue(type_name.GetBuffer(0),value_name.GetBuffer(0))) { + m_ValuesListBox.DeleteString(index); + } +} + +void CDallasUserTypesDlg::OnOK() +{ + // TODO: Add extra validation here + + CDialog::OnOK(); +} + +void CDallasUserTypesDlg::OnSelchangeUtypeCombo() +{ + int index; + CString name; + + CDallasMainDlg *m_DallasModelessDlgPtr; + m_DallasModelessDlgPtr = GetDallasDialogPtr(); + + index=m_UserTypeCombo.GetCurSel(); + if(index==CB_ERR) return; + + m_UserTypeCombo.GetLBText(index,name); + if(name.IsEmpty()) return; + + last_type_selected=name; + + // If Dallas is up, fill in the user type and value boxes + if(m_DallasModelessDlgPtr!=NULL) { + m_DallasModelessDlgPtr->FillValuesBox(&m_ValuesListBox,name.GetBuffer(0)); + } +} + +void CDallasUserTypesDlg::OnDblclkValuesList() +{ + OnChangeButton(); +} diff --git a/editor/DallasUserTypesDlg.h b/editor/DallasUserTypesDlg.h new file mode 100644 index 00000000..f9a77a9d --- /dev/null +++ b/editor/DallasUserTypesDlg.h @@ -0,0 +1,53 @@ +#if !defined(AFX_DALLASUSERTYPESDLG_H__92061D21_B460_11D2_A4E0_00A0C96ED60D__INCLUDED_) +#define AFX_DALLASUSERTYPESDLG_H__92061D21_B460_11D2_A4E0_00A0C96ED60D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DallasUserTypesDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDallasUserTypesDlg dialog + +class CDallasUserTypesDlg : public CDialog +{ +// Construction +public: + CDallasUserTypesDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CDallasUserTypesDlg) + enum { IDD = IDD_DALLAS_USERTYPES_DIALOG }; + CListBox m_ValuesListBox; + CComboBox m_UserTypeCombo; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDallasUserTypesDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDallasUserTypesDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnAddButton(); + afx_msg void OnChangeButton(); + afx_msg void OnDeleteButton(); + virtual void OnOK(); + afx_msg void OnSelchangeUtypeCombo(); + afx_msg void OnDblclkValuesList(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DALLASUSERTYPESDLG_H__92061D21_B460_11D2_A4E0_00A0C96ED60D__INCLUDED_) diff --git a/editor/DallasUtilities.cpp b/editor/DallasUtilities.cpp new file mode 100644 index 00000000..b8951747 --- /dev/null +++ b/editor/DallasUtilities.cpp @@ -0,0 +1,159 @@ +/* +* $Logfile: /DescentIII/Main/Editor/DallasUtilities.cpp $ +* $Revision: 1.1.1.1 $ +* $Date: 2003-08-26 03:57:37 $ +* $Author: kevinb $ +* +* Code for DALLAS related utility functions +* +* $Log: not supported by cvs2svn $ + * + * 6 6/09/99 7:06p Jeff + * stub functions added. #ifdef NEWEDITORs added, files changed, to get + * Dallas integrated into new editor + * + * 5 2/19/99 5:35p Nate + * Added new types and events + * + * 4 12/16/98 8:45p Nate + * Added loading of Actions + * + * 3 12/15/98 7:48p Nate + * Fixed minor buffering problem + * + * 2 12/14/98 12:45p Nate + * Initial Version +* +* $NoKeywords: $ +*/ + +#include "stdafx.h" + +#include +#include + +#include "pserror.h" +#include "cfile.h" +#include "mem.h" +#include "mono.h" +#include "psglob.h" +#include "manage.h" +#include "gamefile.h" + +#include "DallasUtilities.h" + + +// Removes any whitespace padding from the end of a string +void RemoveTrailingWhitespace(char *s) +{ + int last_char_pos; + + last_char_pos=strlen(s)-1; + while(last_char_pos>=0 && isspace(s[last_char_pos])) { + s[last_char_pos]='\0'; + last_char_pos--; + } +} + +// Returns a pointer to the first non-whitespace char in given string +char *SkipInitialWhitespace(char *s) +{ + while((*s)!='\0' && isspace(*s)) + s++; + + return(s); +} + + +class tFindInManage +{ +public: + tFindInManage() {searching = false;} + + bool searching; + bool in_Gamefiles; + int curr_index; + char glob_string[PAGENAME_LEN]; +}; +tFindInManage FindInManageData; + + + +bool FindManageFirst(char *buffer,char *wildcard) +{ +#ifndef NEWEDITOR + if(FindInManageData.searching) + FindManageClose(); + + FindInManageData.searching = true; + strcpy(FindInManageData.glob_string,wildcard); + FindInManageData.curr_index = 0; + FindInManageData.in_Gamefiles = true; + + return FindManageNext(buffer); +#else + return false; +#endif +} + +bool FindManageNext(char *buffer) +{ +#ifndef NEWEDITOR + if(!FindInManageData.searching) + return false; + + if(FindInManageData.in_Gamefiles) + { + + for(;FindInManageData.curr_index 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DallasVectorPromptDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDallasVectorPromptDialog dialog + +class CDallasVectorPromptDialog : public CDialog +{ +// Construction +public: + CDallasVectorPromptDialog(CWnd* pParent = NULL); // standard constructor + + float m_PromptData1; + float m_PromptData2; + float m_PromptData3; + +// Dialog Data + //{{AFX_DATA(CDallasVectorPromptDialog) + enum { IDD = IDD_DALLAS_VECTOR_DIALOG }; + CEdit m_Data3Edit; + CEdit m_Data2Edit; + CEdit m_Data1Edit; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDallasVectorPromptDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDallasVectorPromptDialog) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DALLASVECTORPROMPTDIALOG_H__9E6377E1_95AF_11D2_A4E0_00A0C96ED60D__INCLUDED_) diff --git a/editor/DeathDialog.cpp b/editor/DeathDialog.cpp new file mode 100644 index 00000000..d60070ec --- /dev/null +++ b/editor/DeathDialog.cpp @@ -0,0 +1,522 @@ +// DeathDialog.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "DeathDialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +//Stuff for Copy/Paste +static death_info Paste_data; +static bool Paste_data_used = 0; + +///////////////////////////////////////////////////////////////////////////// +// CDeathDialog dialog + + +CDeathDialog::CDeathDialog(death_info *death_info,CWnd* pParent /*=NULL*/) + : CDialog(CDeathDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDeathDialog) + m_explosion_size_radio = -1; + m_delay_max = 0.0f; + m_delay_min = 0.0f; + //}}AFX_DATA_INIT + + m_death_info_ptr = death_info; + + m_flags = death_info->flags; + m_delay_min = death_info->delay_min; + m_delay_max = death_info->delay_max; +} + + +void CDeathDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDeathDialog) + DDX_Radio(pDX, IDC_DEATH_EXPLOSION_SMALL, m_explosion_size_radio); + DDX_Text(pDX, IDC_DEATH_DELAY_MAX, m_delay_max); + DDV_MinMaxFloat(pDX, m_delay_max, 0.f, 10.f); + DDX_Text(pDX, IDC_DEATH_DELAY_MIN, m_delay_min); + DDV_MinMaxFloat(pDX, m_delay_min, 0.f, 10.f); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDeathDialog, CDialog) + //{{AFX_MSG_MAP(CDeathDialog) + ON_BN_CLICKED(IDC_DEATH_BREAKS_APART, OnDeathBreaksApart) + ON_BN_CLICKED(IDC_DEATH_COMMON_ANIMAL, OnDeathCommonAnimal) + ON_BN_CLICKED(IDC_DEATH_COMMON_DESCENT, OnDeathCommonDescent) + ON_BN_CLICKED(IDC_DEATH_COMMON_QUICK_EXPLOSION, OnDeathCommonQuickExplosion) + ON_BN_CLICKED(IDC_DEATH_COMMON_R2D2, OnDeathCommonR2D2) + ON_BN_CLICKED(IDC_DEATH_COMMON_SHOOT_UP, OnDeathCommonShootUp) + ON_BN_CLICKED(IDC_DEATH_CONTACT_BREAKS_APART, OnDeathContactBreaksApart) + ON_BN_CLICKED(IDC_DEATH_CONTACT_EXPLODES, OnDeathContactExplodes) + ON_BN_CLICKED(IDC_DEATH_CONTACT_REMAINS, OnDeathContactRemains) + ON_BN_CLICKED(IDC_DEATH_COPY, OnDeathCopy) + ON_BN_CLICKED(IDC_DEATH_DEBRIS_CONTACT_EXPLODES, OnDeathDebrisContactExplodes) + ON_BN_CLICKED(IDC_DEATH_DEBRIS_CONTACT_REMAINS, OnDeathDebrisContactRemains) + ON_BN_CLICKED(IDC_DEATH_DELAY_FIREBALLS, OnDeathDelayFireballs) + ON_BN_CLICKED(IDC_DEATH_DELAY_FLYING, OnDeathDelayFlying) + ON_BN_CLICKED(IDC_DEATH_DELAY_LOSES_ANTIGRAV, OnDeathDelayLosesAntigrav) + ON_EN_CHANGE(IDC_DEATH_DELAY_MAX, OnChangeDeathDelayMax) + ON_EN_CHANGE(IDC_DEATH_DELAY_MIN, OnChangeDeathDelayMin) + ON_BN_CLICKED(IDC_DEATH_DELAY_SPARKS, OnDeathDelaySparks) + ON_BN_CLICKED(IDC_DEATH_EXPLODES, OnDeathExplodes) + ON_BN_CLICKED(IDC_DEATH_EXPLOSION_LARGE, OnDeathExplosionLarge) + ON_BN_CLICKED(IDC_DEATH_EXPLOSION_MEDIUM, OnDeathExplosionMedium) + ON_BN_CLICKED(IDC_DEATH_EXPLOSION_SMALL, OnDeathExplosionSmall) + ON_BN_CLICKED(IDC_DEATH_PASTE, OnDeathPaste) + ON_BN_CLICKED(IDC_DEATH_BLAST_RING, OnDeathBlastRing) + ON_BN_CLICKED(IDC_DEATH_CONTACT_BLAST_RING, OnDeathContactBlastRing) + ON_BN_CLICKED(IDC_DEATH_CONTACT_FIREBALL, OnDeathContactFireball) + ON_BN_CLICKED(IDC_DEATH_DEBRIS_CONTACT_BLAST_RING, OnDeathDebrisContactBlastRing) + ON_BN_CLICKED(IDC_DEATH_DEBRIS_CONTACT_FIREBALL, OnDeathDebrisContactFireball) + ON_BN_CLICKED(IDC_DEATH_DEBRIS_SMOKES, OnDeathDebrisSmokes) + ON_BN_CLICKED(IDC_DEATH_DELAY_FROM_ANIM, OnDeathDelayFromAnim) + ON_BN_CLICKED(IDC_DEATH_DELAY_SMOKE, OnDeathDelaySmoke) + ON_BN_CLICKED(IDC_DEATH_FIREBALL, OnDeathFireball) + ON_BN_CLICKED(IDC_DEATH_LOSES_ANTIGRAV, OnDeathLosesAntigrav) + ON_BN_CLICKED(IDC_DEATH_REMAINS, OnDeathRemains) + ON_BN_CLICKED(IDC_DEATH_DELAY_FADE_AWAY, OnDeathDelayFadeAway) + ON_BN_CLICKED(IDC_DEATH_FADES_AWAY, OnDeathFadesAway) + ON_BN_CLICKED(IDC_DEATH_DELAY_SOUND, OnDeathDelaySound) + ON_BN_CLICKED(IDC_DEATH_DELAY_NO_TUMBLE, OnDeathDelayNoTumble) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDeathDialog message handlers + + +BOOL CDeathDialog::OnInitDialog() +{ + CDialog::OnInitDialog(); + + UpdateDialog(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +//Handy macros +#define SET_CHECK(id,state) ((CButton *) GetDlgItem(id))->SetCheck((state) != 0) +#define GET_CHECK(id) ((CButton *) GetDlgItem(id))->GetCheck() +#define ENABLE(id,state) ((CButton *) GetDlgItem(id))->EnableWindow((state) != 0) + +void CDeathDialog::UpdateDialog() +{ + //Set member variables for explosion size radio button + m_explosion_size_radio = (m_flags & DF_EXPL_SIZE_MASK) >> DF_EXPL_SIZE_SHIFT; + + //Update the dialog from member variables + UpdateData(false); + + //Set the delay checkboxes + SET_CHECK(IDC_DEATH_DELAY_FROM_ANIM,(m_flags & DF_DELAY_FROM_ANIM)); + SET_CHECK(IDC_DEATH_DELAY_LOSES_ANTIGRAV,(m_flags & DF_DELAY_LOSES_ANTIGRAV)); + SET_CHECK(IDC_DEATH_DELAY_SPARKS,(m_flags & DF_DELAY_SPARKS)); + SET_CHECK(IDC_DEATH_DELAY_SMOKE,(m_flags & DF_DELAY_SMOKES)); + SET_CHECK(IDC_DEATH_DELAY_FLYING,(m_flags & DF_DELAY_FLYING)); + SET_CHECK(IDC_DEATH_DELAY_FIREBALLS,(m_flags & DF_DELAY_FIREBALL)); + SET_CHECK(IDC_DEATH_DELAY_FADE_AWAY,(m_flags & DF_DELAY_FADE_AWAY)); + SET_CHECK(IDC_DEATH_DELAY_SOUND,(m_flags & DF_DELAY_SOUND)); + SET_CHECK(IDC_DEATH_DELAY_NO_TUMBLE,(m_flags & DF_DELAY_NO_TUMBLE_FLY)); + + //Set the death checkboxes + SET_CHECK(IDC_DEATH_FIREBALL,(m_flags & DF_FIREBALL)); + SET_CHECK(IDC_DEATH_BREAKS_APART,(m_flags & DF_BREAKS_APART)); + SET_CHECK(IDC_DEATH_FADES_AWAY,(m_flags & DF_FADE_AWAY)); + SET_CHECK(IDC_DEATH_BLAST_RING,(m_flags & DF_BLAST_RING)); + SET_CHECK(IDC_DEATH_REMAINS,(m_flags & DF_REMAINS)); + SET_CHECK(IDC_DEATH_LOSES_ANTIGRAV,(m_flags & DF_LOSES_ANTIGRAV)); + + //Set the contact checkboxes + SET_CHECK(IDC_DEATH_CONTACT_FIREBALL,(m_flags & DF_CONTACT_FIREBALL)); + SET_CHECK(IDC_DEATH_CONTACT_BREAKS_APART,(m_flags & DF_CONTACT_BREAKS_APART)); + SET_CHECK(IDC_DEATH_CONTACT_BLAST_RING,(m_flags & DF_CONTACT_BLAST_RING)); + SET_CHECK(IDC_DEATH_CONTACT_REMAINS,(m_flags & DF_CONTACT_REMAINS)); + + //Set the debris checkbox + SET_CHECK(IDC_DEATH_DEBRIS_SMOKES,(m_flags & DF_DEBRIS_SMOKES)); + + //Set the debris contact checkboxes + SET_CHECK(IDC_DEATH_DEBRIS_CONTACT_FIREBALL,(m_flags & DF_DEBRIS_FIREBALL)); + SET_CHECK(IDC_DEATH_DEBRIS_CONTACT_BLAST_RING,(m_flags & DF_DEBRIS_BLAST_RING)); + SET_CHECK(IDC_DEATH_DEBRIS_CONTACT_REMAINS,(m_flags & DF_DEBRIS_REMAINS)); + + //Enable/disable delay options + bool delay = ((m_flags & DF_DELAY_FROM_ANIM) || (m_delay_min != 0.0) || (m_delay_max != 0.0)); + ENABLE(IDC_DEATH_DELAY_GROUP,delay); + ENABLE(IDC_DEATH_DELAY_LOSES_ANTIGRAV,delay); + ENABLE(IDC_DEATH_DELAY_SPARKS,delay); + ENABLE(IDC_DEATH_DELAY_SMOKE,delay); + ENABLE(IDC_DEATH_DELAY_FLYING,delay); + ENABLE(IDC_DEATH_DELAY_FIREBALLS,delay); + ENABLE(IDC_DEATH_DELAY_FADE_AWAY,delay); + ENABLE(IDC_DEATH_DELAY_SOUND,delay); + ENABLE(IDC_DEATH_DELAY_NO_TUMBLE,delay && (m_flags & DF_DELAY_FLYING)); + + //Enable/disable delay times + bool user_delay = !(m_flags & DF_DELAY_FROM_ANIM); + ENABLE(IDC_DEATH_DELAY_MIN,user_delay); + ENABLE(IDC_DEATH_DELAY_MAX,user_delay); + ENABLE(IDC_DEATH_DELAY_MIN_LABEL,user_delay); + ENABLE(IDC_DEATH_DELAY_MAX_LABEL,user_delay); + + //Enable/disable contact options + ENABLE(IDC_DEATH_CONTACT_FIREBALL,delay); + ENABLE(IDC_DEATH_CONTACT_BREAKS_APART,delay); + ENABLE(IDC_DEATH_CONTACT_BLAST_RING,delay); + ENABLE(IDC_DEATH_CONTACT_REMAINS,delay); + ENABLE(IDC_DEATH_CONTACT_GROUP,delay); + + //Enable/disable explosion options + bool explodes = ((m_flags & DF_FIREBALL) != 0); + ENABLE(IDC_DEATH_EXPLOSION_SMALL,explodes); + ENABLE(IDC_DEATH_EXPLOSION_MEDIUM,explodes); + ENABLE(IDC_DEATH_EXPLOSION_LARGE,explodes); + ENABLE(IDC_DEATH_EXPLOSION_OPTIONS_GROUP,explodes); + + //Enable/disable debris options + bool breaks_apart = ((m_flags & DF_BREAKS_APART) != 0); + ENABLE(IDC_DEATH_DEBRIS_CONTACT_FIREBALL,breaks_apart); + ENABLE(IDC_DEATH_DEBRIS_CONTACT_BLAST_RING,breaks_apart); + ENABLE(IDC_DEATH_DEBRIS_CONTACT_REMAINS,breaks_apart); + ENABLE(IDC_DEATH_DEBRIS_CONTACT_GROUP,breaks_apart); + ENABLE(IDC_DEATH_DEBRIS_SMOKES,breaks_apart); + ENABLE(IDC_DEATH_DEBRIS_OPTIONS_GROUP,breaks_apart); + + //Enable/disable Paste + ENABLE(IDC_DEATH_PASTE,Paste_data_used); +} + +void CDeathDialog::OnDeathDelayFromAnim() +{ + m_flags ^= DF_DELAY_FROM_ANIM; + + UpdateDialog(); +} + +void CDeathDialog::OnChangeDeathDelayMin() +{ + // TODO: If this is a RICHEDIT control, the control will not + // send this notification unless you override the CDialog::OnInitDialog() + // function and call CRichEditCtrl().SetEventMask() + // with the ENM_CHANGE flag ORed into the mask. + + //Update the member variables from the dialog + UpdateData(true); + + UpdateDialog(); +} + +void CDeathDialog::OnChangeDeathDelayMax() +{ + // TODO: If this is a RICHEDIT control, the control will not + // send this notification unless you override the CDialog::OnInitDialog() + // function and call CRichEditCtrl().SetEventMask() + // with the ENM_CHANGE flag ORed into the mask. + + //Update the member variables from the dialog + UpdateData(true); + + UpdateDialog(); +} + +void CDeathDialog::OnDeathDelaySparks() +{ + m_flags ^= DF_DELAY_SPARKS; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathDelayFireballs() +{ + m_flags ^= DF_DELAY_FIREBALL; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathDelaySmoke() +{ + m_flags ^= DF_DELAY_SMOKES; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathDelayFlying() +{ + m_flags ^= DF_DELAY_FLYING; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathDelayLosesAntigrav() +{ + m_flags ^= DF_DELAY_LOSES_ANTIGRAV; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathDelayFadeAway() +{ + m_flags ^= DF_DELAY_FADE_AWAY; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathExplodes() +{ + m_flags ^= DF_FIREBALL; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathBreaksApart() +{ + m_flags ^= DF_BREAKS_APART; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathExplosionSmall() +{ + m_flags = (m_flags & ~DF_EXPL_SIZE_MASK) | DF_EXPL_SMALL; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathExplosionMedium() +{ + m_flags = (m_flags & ~DF_EXPL_SIZE_MASK) | DF_EXPL_MEDIUM; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathExplosionLarge() +{ + m_flags = (m_flags & ~DF_EXPL_SIZE_MASK) | DF_EXPL_LARGE; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathBlastRing() +{ + m_flags ^= DF_BLAST_RING; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathContactBreaksApart() +{ + m_flags ^= DF_CONTACT_BREAKS_APART; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathContactExplodes() +{ + m_flags ^= DF_CONTACT_FIREBALL; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathContactRemains() +{ + m_flags ^= DF_CONTACT_REMAINS; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathDebrisContactExplodes() +{ + m_flags ^= DF_DEBRIS_FIREBALL; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathDebrisContactRemains() +{ + m_flags ^= DF_DEBRIS_REMAINS; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathCommonDescent() +{ + m_flags = DF_DELAY_FIREBALL + + DF_FIREBALL + + DF_BREAKS_APART + + DF_DEBRIS_FIREBALL + + DF_EXPL_MEDIUM; + m_delay_min = m_delay_max = 2.0; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathCommonQuickExplosion() +{ + m_flags = DF_FIREBALL + + DF_BREAKS_APART + + DF_DEBRIS_FIREBALL + + DF_EXPL_MEDIUM; + m_delay_min = m_delay_max = 0.0; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathCommonShootUp() +{ + m_flags = DF_DELAY_FLYING + + DF_FIREBALL + + DF_BREAKS_APART + + DF_DEBRIS_FIREBALL + + DF_EXPL_MEDIUM; + m_delay_min = 1.0; + m_delay_max = 3.0; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathCommonR2D2() +{ + m_flags = DF_DELAY_SPARKS + + DF_FIREBALL + + DF_BREAKS_APART + + DF_DEBRIS_FIREBALL + + DF_EXPL_MEDIUM; + m_delay_min = 2.0; + m_delay_max = 4.0; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathCommonAnimal() +{ + m_flags = DF_CONTACT_REMAINS; + m_delay_min = m_delay_max = 0.0; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathCopy() +{ + Paste_data.flags = m_flags; + Paste_data.delay_min = m_delay_min; + Paste_data.delay_max = m_delay_max; + + Paste_data_used = 1; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathPaste() +{ + m_flags = Paste_data.flags; + m_delay_min = Paste_data.delay_min; + m_delay_max = Paste_data.delay_max; + + UpdateDialog(); +} + +#include "pserror.h" + +void CDeathDialog::OnOK() +{ + if (m_delay_max < m_delay_min) { + EditorMessageBox("Max delay must be greater than or equal to min delay."); + return; + } + + //Copy data into input struct + m_death_info_ptr->flags = m_flags; + m_death_info_ptr->delay_min = m_delay_min; + m_death_info_ptr->delay_max = m_delay_max; + + CDialog::OnOK(); +} + +void CDeathDialog::OnDeathContactBlastRing() +{ + m_flags ^= DF_CONTACT_BLAST_RING; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathContactFireball() +{ + m_flags ^= DF_CONTACT_FIREBALL; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathDebrisContactBlastRing() +{ + m_flags ^= DF_DEBRIS_BLAST_RING; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathDebrisContactFireball() +{ + m_flags ^= DF_DEBRIS_FIREBALL; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathDebrisSmokes() +{ + m_flags ^= DF_DEBRIS_SMOKES; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathFireball() +{ + m_flags ^= DF_FIREBALL; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathLosesAntigrav() +{ + m_flags ^= DF_LOSES_ANTIGRAV; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathRemains() +{ + m_flags ^= DF_REMAINS; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathFadesAway() +{ + m_flags ^= DF_FADE_AWAY; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathDelaySound() +{ + m_flags ^= DF_DELAY_SOUND; + + UpdateDialog(); +} + +void CDeathDialog::OnDeathDelayNoTumble() +{ + m_flags ^= DF_DELAY_NO_TUMBLE_FLY; + + UpdateDialog(); +} diff --git a/editor/DeathDialog.h b/editor/DeathDialog.h new file mode 100644 index 00000000..ce76c455 --- /dev/null +++ b/editor/DeathDialog.h @@ -0,0 +1,98 @@ +#if !defined(AFX_DEATHDIALOG_H__ADECD300_ABA8_11D2_A13A_0060089A83BE__INCLUDED_) +#define AFX_DEATHDIALOG_H__ADECD300_ABA8_11D2_A13A_0060089A83BE__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DeathDialog.h : header file +// + +#include "DeathInfo.h" +#include "objinfo.h" + +///////////////////////////////////////////////////////////////////////////// +// CDeathDialog dialog + +class CDeathDialog : public CDialog +{ +// Construction +public: + CDeathDialog(death_info *death_info,CWnd* pParent = NULL); // standard constructor + + death_info *m_death_info_ptr; + int m_flags; + + +// Dialog Data + //{{AFX_DATA(CDeathDialog) + enum { IDD = IDD_DEATH_DIALOG }; + int m_explosion_size_radio; + float m_delay_max; + float m_delay_min; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDeathDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +private: + void UpdateDialog(); + +protected: + + + // Generated message map functions + //{{AFX_MSG(CDeathDialog) + afx_msg void OnDeathBreaksApart(); + afx_msg void OnDeathCommonAnimal(); + afx_msg void OnDeathCommonDescent(); + afx_msg void OnDeathCommonQuickExplosion(); + afx_msg void OnDeathCommonR2D2(); + afx_msg void OnDeathCommonShootUp(); + afx_msg void OnDeathContactBreaksApart(); + afx_msg void OnDeathContactExplodes(); + afx_msg void OnDeathContactRemains(); + afx_msg void OnDeathCopy(); + afx_msg void OnDeathDebrisContactExplodes(); + afx_msg void OnDeathDebrisContactRemains(); + afx_msg void OnDeathDelayFireballs(); + afx_msg void OnDeathDelayFlying(); + afx_msg void OnDeathDelayLosesAntigrav(); + afx_msg void OnChangeDeathDelayMax(); + afx_msg void OnChangeDeathDelayMin(); + afx_msg void OnDeathDelaySparks(); + afx_msg void OnDeathExplodes(); + afx_msg void OnDeathExplosionLarge(); + afx_msg void OnDeathExplosionMedium(); + afx_msg void OnDeathExplosionSmall(); + afx_msg void OnDeathPaste(); + afx_msg void OnDeathBlastRing(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnDeathContactBlastRing(); + afx_msg void OnDeathContactFireball(); + afx_msg void OnDeathDebrisContactBlastRing(); + afx_msg void OnDeathDebrisContactFireball(); + afx_msg void OnDeathDebrisSmokes(); + afx_msg void OnDeathDelayFromAnim(); + afx_msg void OnDeathDelaySmoke(); + afx_msg void OnDeathFireball(); + afx_msg void OnDeathLosesAntigrav(); + afx_msg void OnDeathRemains(); + afx_msg void OnDeathDelayFadeAway(); + afx_msg void OnDeathFadesAway(); + afx_msg void OnDeathDelaySound(); + afx_msg void OnDeathDelayNoTumble(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DEATHDIALOG_H__ADECD300_ABA8_11D2_A13A_0060089A83BE__INCLUDED_) diff --git a/editor/DoorwayDialog.cpp b/editor/DoorwayDialog.cpp new file mode 100644 index 00000000..3462df58 --- /dev/null +++ b/editor/DoorwayDialog.cpp @@ -0,0 +1,683 @@ +/* + * $Logfile: /DescentIII/Main/editor/DoorwayDialog.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:57:37 $ + * $Author: kevinb $ + * + * Doorway keypad + * + * $Log: not supported by cvs2svn $ + * + * 23 5/05/99 2:02a Matt + * Added doorway flag to tell the Guide-Bot to ignore the locked state of + * the door. + * + * 22 4/03/99 7:55p Matt + * Use new keypad update system instead of timer to update. + * + * 21 3/05/99 1:51p Kevin + * Fixed small crash bug + * + * 20 3/01/99 10:37a Matt + * Update doorway tab when the door object is renamed + * + * 19 2/06/99 10:03p Matt + * Added keys system + * + * 18 2/04/99 2:05p Matt + * Added blastable doors + * + * 17 1/29/99 12:48p Matt + * Rewrote the doorway system + * + * 16 9/22/98 12:02p Matt + * Fixed compile warnings + * + * 15 9/08/98 12:06p Jason + * added automatic reinitting of doors when rooms get deleted + * + * 14 9/02/98 4:32p Matt + * Added some error checking when placing a door. + * + * 13 6/15/98 4:00p Jason + * replaced monochromatic polymodel lighting with rgb lighting + * + * 12 4/20/98 2:52p Jason + * added doorway reinit function + * + * 11 4/07/98 11:05a Kevin + * For Samir, added m_Active to the if statement in the timer interrupt + * + * 10 4/02/98 3:54p Jason + * first pass in getting polymodel paging to work + * + * 9 12/19/97 11:25a Samir + * g3_StartFrame and g3_EndFrame replaced by EditorStartFrame and + * EditorEndFrame + * + * 8 10/03/97 12:24p Jason + * added new keys for doorways + * + * 7 9/29/97 12:09p Jason + * added functionality to doorway system + * + * 6 9/23/97 12:29p Jason + * fixed m_Active bug + * + * 5 9/17/97 1:01p Matt + * Ripped out segment code + * + * 4 9/11/97 5:46p Jason + * first pass at getting doors to work with room engine + * + * 3 7/24/97 6:11p Matt + * Created symbolic constant for default zoom, and used it every place + * that specifies zoom + * + * 20 6/03/97 4:55p Mark + * + * 20 6/03/97 4:51p Jeff + * Added Context Sensitive Help + * + * 19 4/02/97 5:15p Samir + * Added a Opened checkbox to mark a door as open or closed initially + * + * 18 4/01/97 11:00p Matt + * Changed editor to keep a viewer object (type camera) seperate from the + * player object. This camera, and not the player, is now moved by + * slewing, the C key, etc. When going into the game, the viewer position + * & orientation are copied to the player. When going back to the editor, + * the player position is copied to the viewer, and the player object is + * reset to its start location. + * + * 17 3/31/97 5:57p Matt + * Revamped mine update flags + * + * 16 3/26/97 5:43p Samir + * Fixed refresh of doorway selector when changing state of door page. + * + * 15 3/25/97 6:31p Samir + * Now you can select from different 3d doors hopefully. + * + * 14 3/24/97 6:47p Samir + * Fixed some place,remove doorway probs with 3d doors. Made some state + * vars static for multiple instances of dialog. + * + * 13 3/20/97 12:10p Samir + * Fixed prob when going into fullscreen with doorway keypad visible. + * + * 12 3/19/97 7:02p Samir + * If adding door segment fails, don't register it as a door! And + * deactivated moving doorways from one seg to another for now. + * + * 11 3/18/97 11:35a Samir + * Fixed user interface problems. + * + * $NoKeywords: $ + */ + +// DoorwayDialog.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "DoorwayDialog.h" + +#include "door.h" +#include "HView.h" +#include "HRoom.h" +#include "polymodel.h" +#include "edoors.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +int Current_door_room=-1; + +///////////////////////////////////////////////////////////////////////////// +// CDoorwayDialog dialog + + +CDoorwayDialog::CDoorwayDialog(CWnd* pParent /*=NULL*/) + : CKeypadDialog(CDoorwayDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDoorwayDialog) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + +// m_SelectionType = DOORWAY_DOOR; +} + + +void CDoorwayDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDoorwayDialog) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDoorwayDialog, CDialog) + //{{AFX_MSG_MAP(CDoorwayDialog) + ON_WM_VSCROLL() + ON_WM_HSCROLL() + ON_WM_SIZE() + ON_WM_PAINT() + ON_BN_CLICKED(IDC_DOORWAY_PLACEDOOR, OnDoorwayPlaceDoorway) + ON_BN_CLICKED(IDC_NEXT_DOOR, OnNextDoor) + ON_BN_CLICKED(IDC_PREV_DOOR, OnPrevDoor) + ON_BN_CLICKED(IDC_DOORWAY_LOCKED, OnDoorwayLocked) + ON_BN_CLICKED(IDC_KEY1_CHECK, OnKey1Check) + ON_BN_CLICKED(IDC_KEY2_CHECK, OnKey2Check) + ON_BN_CLICKED(IDC_KEY3_CHECK, OnKey3Check) + ON_BN_CLICKED(IDC_KEY4_CHECK, OnKey4Check) + ON_BN_CLICKED(IDC_KEY5_CHECK, OnKey5Check) + ON_BN_CLICKED(IDC_KEY6_CHECK, OnKey6Check) + ON_BN_CLICKED(IDC_KEY7_CHECK, OnKey7Check) + ON_BN_CLICKED(IDC_KEY8_CHECK, OnKey8Check) + ON_BN_CLICKED(IDC_DOORWAY_ATTACHDOOR, OnDoorwayAttachDoor) + ON_BN_CLICKED(IDC_DOORWAY_AUTO, OnDoorwayAuto) + ON_EN_KILLFOCUS(IDC_DOORWAY_POS_EDIT, OnKillfocusDoorwayPosEdit) + ON_EN_KILLFOCUS(IDC_DOORWAY_HITPOINT_EDIT, OnKillfocusDoorwayHitpointEdit) + ON_BN_CLICKED(IDC_DOORWAY_KEY_ALL, OnDoorwayKeyAll) + ON_BN_CLICKED(IDC_DOORWAY_KEY_ONLY_ONE, OnDoorwayKeyOnlyOne) + ON_BN_CLICKED(IDC_DOORWAY_GB_IGNORE_LOCKED, OnDoorwayGBIgnoreLocked) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDoorwayDialog message handlers + +void CDoorwayDialog::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + // TODO: Add your message handler code here and/or call default + + CKeypadDialog::OnVScroll(nSBCode, nPos, pScrollBar); +} + + +void CDoorwayDialog::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + // TODO: Add your message handler code here and/or call default + + CKeypadDialog::OnHScroll(nSBCode, nPos, pScrollBar); +} + + +void CDoorwayDialog::OnSize(UINT nType, int cx, int cy) +{ + CKeypadDialog::OnSize(nType, cx, cy); + + +} + + +void CDoorwayDialog::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + UpdateDialog(); +} + + +BOOL CDoorwayDialog::OnInitDialog() +{ + CDialog::OnInitDialog(); + UpdateDialog(); + return TRUE; +} + + +void CDoorwayDialog::OnOK() +{ + CWnd *focus = CWnd::GetFocus(); + if (focus) focus->GetNextWindow()->SetFocus(); +} + +void CDoorwayDialog::EnableCurrentItems(bool state) +{ + ((CButton *) GetDlgItem(IDC_DOORWAY_ID))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_DOORWAY_LOCKED))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_DOORWAY_GB_IGNORE_LOCKED))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_DOORWAY_AUTO))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_DOORWAY_CURRENT_BOX))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_DOORWAY_POS_TEXT))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_DOORWAY_POS_EDIT))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_DOORWAY_HITPOINT_TEXT))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_DOORWAY_HITPOINT_EDIT))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_DOORWAY_KEYS_TEXT))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_DOORWAY_KEY_ALL))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_DOORWAY_KEY_ONLY_ONE))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_KEY1_CHECK))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_KEY2_CHECK))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_KEY3_CHECK))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_KEY4_CHECK))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_KEY5_CHECK))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_KEY6_CHECK))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_KEY7_CHECK))->EnableWindow(state); + ((CButton *) GetDlgItem(IDC_KEY8_CHECK))->EnableWindow(state); +} + + +// --------------------------------------------------------------------------- +// Update doorway key functions functions +// --------------------------------------------------------------------------- + +char last_name[OBJ_NAME_LEN +1]; + +void CDoorwayDialog::UpdateDialog() +{ + if (!m_Active) return; + + if (Num_doors<=0) + return; + if (Doors[D3EditState.current_door].used==0) + D3EditState.current_door=GetNextDoor (D3EditState.current_door); + + int door_handle=D3EditState.current_door; + + CEdit *ebox=(CEdit *) GetDlgItem (IDC_DOORWAYSELEDIT); + ebox->SetWindowText (Doors[door_handle].name); + DrawDoorwayDoorPic(); + + ((CButton *) GetDlgItem(IDC_DOORWAY_ATTACHDOOR))->EnableWindow(Placed_door != -1); + + ebox=(CEdit *) GetDlgItem (IDC_DOORWAY_ID); + + if (Cur_object_index==-1 || Objects[Cur_object_index].type!=OBJ_DOOR) + { + ebox->SetWindowText ("No doorway selected"); + Current_door_room = -1; + EnableCurrentItems(0); + } + else + { + char str[250]; + object *objp = &Objects[Cur_object_index]; + + EnableCurrentItems(1); + + Current_door_room = objp->roomnum; + + ASSERT(Rooms[Current_door_room].flags & RF_DOOR); + + strcpy(last_name,Objects[Cur_object_index].name?Objects[Cur_object_index].name:""); + sprintf (str,"Door: %s ",last_name); + ebox->SetWindowText (str); + + doorway *dw = Rooms[Current_door_room].doorway_data; + + sprintf(str,"%.2f",dw->position); + ebox=(CEdit *) GetDlgItem(IDC_DOORWAY_POS_EDIT); + ebox->SetWindowText(str); + + //Update key check boxes + CButton *bbox = (CButton *)GetDlgItem(IDC_DOORWAY_LOCKED); + bbox->SetCheck(dw->flags & DF_LOCKED); + + bbox = (CButton *)GetDlgItem(IDC_DOORWAY_AUTO); + bbox->SetCheck(dw->flags & DF_AUTO); + + bbox = (CButton *)GetDlgItem(IDC_DOORWAY_GB_IGNORE_LOCKED); + bbox->SetCheck(dw->flags & DF_GB_IGNORE_LOCKED); + + bbox = (CButton *)GetDlgItem(IDC_KEY1_CHECK); + bbox->SetCheck(dw->keys_needed & KEY_FLAG(1)); + + bbox = (CButton *)GetDlgItem(IDC_KEY2_CHECK); + bbox->SetCheck(dw->keys_needed & KEY_FLAG(2)); + + bbox = (CButton *)GetDlgItem(IDC_KEY3_CHECK); + bbox->SetCheck(dw->keys_needed & KEY_FLAG(3)); + + bbox = (CButton *)GetDlgItem(IDC_KEY4_CHECK); + bbox->SetCheck(dw->keys_needed & KEY_FLAG(4)); + + bbox = (CButton *)GetDlgItem(IDC_KEY5_CHECK); + bbox->SetCheck(dw->keys_needed & KEY_FLAG(5)); + + bbox = (CButton *)GetDlgItem(IDC_KEY6_CHECK); + bbox->SetCheck(dw->keys_needed & KEY_FLAG(6)); + + bbox = (CButton *)GetDlgItem(IDC_KEY7_CHECK); + bbox->SetCheck(dw->keys_needed & KEY_FLAG(7)); + + bbox = (CButton *)GetDlgItem(IDC_KEY8_CHECK); + bbox->SetCheck(dw->keys_needed & KEY_FLAG(8)); + + //Update key radio buttons + bbox = (CButton *)GetDlgItem(IDC_DOORWAY_KEY_ALL); + bbox->SetCheck(! (dw->flags & DF_KEY_ONLY_ONE)); + bbox = (CButton *)GetDlgItem(IDC_DOORWAY_KEY_ONLY_ONE); + bbox->SetCheck(dw->flags & DF_KEY_ONLY_ONE); + + //Update hitpoints editing + door *door = &Doors[dw->doornum]; + bool blastable = ((door->flags & DF_BLASTABLE) != 0); + ((CButton *) GetDlgItem(IDC_DOORWAY_HITPOINT_TEXT))->EnableWindow(blastable); + sprintf(str,"%d",(int) objp->shields); + ebox=(CEdit *) GetDlgItem(IDC_DOORWAY_HITPOINT_EDIT); + ebox->SetWindowText(str); + ebox->EnableWindow(blastable); + } +} + + +// update doorway picture + +void CDoorwayDialog::DrawDoorwayDoorPic() +{ + int door_handle=D3EditState.current_door; + vector zero_vector; + vector view_vector={0,0,-20}; + matrix id_matrix; + float norm_angles[30]; + int w, h, bm_handle, x, y; + RECT rect; + CWnd *wnd = GetDlgItem(IDC_DOORPIC); + + Desktop_surf->attach_to_window((unsigned)wnd->m_hWnd); + + wnd->GetWindowRect(&rect); + ScreenToClient(&rect); + + w=rect.right-rect.left; + h=rect.bottom-rect.top; + + m_DoorSurf.create(w, h, BPP_16); + + Desktop_surf->clear(0,0,w,h); + + bm_handle=GetDoorImage (door_handle); + + poly_model *pm=GetPolymodelPointer (bm_handle); + + vm_MakeZero (&zero_vector); + vm_MakeIdentity (&id_matrix); + + for (int i=0;i<30;i++) + norm_angles[i]=0; + + grViewport *vport=new grViewport (&m_DoorSurf); + StartEditorFrame (vport,&view_vector,&id_matrix,D3_DEFAULT_ZOOM); + DrawPolygonModel (&zero_vector,&id_matrix,bm_handle,norm_angles,0,1.0,1.0,1.0); + EndEditorFrame(); + + x = rect.left + ((rect.right-rect.left)/2) - m_DoorSurf.width()/2; + y = rect.top + ((rect.bottom-rect.top)/2) - m_DoorSurf.height()/2; + Desktop_surf->blt(0, 0, &m_DoorSurf); + + delete vport; + m_DoorSurf.free(); + Desktop_surf->attach_to_window((unsigned)NULL); +} + + + +// --------------------------------------------------------------------------- +// Doorway editing functions +// --------------------------------------------------------------------------- + +void CDoorwayDialog::OnDoorwayPlaceDoorway() +{ + if (Num_doors<=0) + return; + + if (D3EditState.current_door == -1) { + OutrageMessageBox("You must have a current door for this operation"); + return; + } + + if (Curroomp->faces[Curface].portal_num != -1) { + OutrageMessageBox("There's already a connection at the current room:face."); + return; + } + + PlaceDoor(Curroomp,Curface,D3EditState.current_door); + + UpdateDialog(); + + World_changed = 1; +} + +/*BOOL CDoorwayDialog::OnHelpInfo(HELPINFO* pHelpInfo) +{ + // TODO: Add your message handler code here and/or call default + WinHelp(HID_DOORWAYTAB,HELP_CONTEXT); + return TRUE; + //return CDialog::OnHelpInfo(pHelpInfo); +}*/ + +void CDoorwayDialog::OnNextDoor() +{ + if (Num_doors<=0) + return; + + D3EditState.current_door=GetNextDoor (D3EditState.current_door); + UpdateDialog(); +} + +void CDoorwayDialog::OnPrevDoor() +{ + if (Num_doors<=0) + return; + + D3EditState.current_door=GetPrevDoor (D3EditState.current_door); + UpdateDialog(); + + +} + +void CDoorwayDialog::OnDoorwayLocked() +{ + if (Current_door_room == -1) + return; + + doorway *dp = Rooms[Current_door_room].doorway_data; + + ASSERT(dp != NULL); + + int c=IsDlgButtonChecked(IDC_DOORWAY_LOCKED); + + if (c) + dp->flags|=DF_LOCKED; + else + dp->flags&=~DF_LOCKED; +} + +void CDoorwayDialog::UpdateKeypad(int mask) +{ + if (mask & (KUF_CUROBJ_CHANGED+KUF_CUROBJ_NAME_CHANGED)) + UpdateDialog(); +} + +void CDoorwayDialog::OnKeyCheck(int id,int keynum) +{ + if (Current_door_room == -1) + return; + + doorway *dp = Rooms[Current_door_room].doorway_data; + + ASSERT(dp != NULL); + + if (IsDlgButtonChecked(id)) + dp->keys_needed |= KEY_FLAG(keynum); + else + dp->keys_needed &= ~KEY_FLAG(keynum); +} + +void CDoorwayDialog::OnKey1Check() +{ + OnKeyCheck(IDC_KEY1_CHECK,1); +} + +void CDoorwayDialog::OnKey2Check() +{ + OnKeyCheck(IDC_KEY2_CHECK,2); +} + +void CDoorwayDialog::OnKey3Check() +{ + OnKeyCheck(IDC_KEY3_CHECK,3); +} + +void CDoorwayDialog::OnKey4Check() +{ + OnKeyCheck(IDC_KEY4_CHECK,4); +} + +void CDoorwayDialog::OnKey5Check() +{ + OnKeyCheck(IDC_KEY5_CHECK,5); +} + +void CDoorwayDialog::OnKey6Check() +{ + OnKeyCheck(IDC_KEY6_CHECK,6); +} + +void CDoorwayDialog::OnKey7Check() +{ + OnKeyCheck(IDC_KEY7_CHECK,7); +} + +void CDoorwayDialog::OnKey8Check() +{ + OnKeyCheck(IDC_KEY8_CHECK,8); +} + + +void CDoorwayDialog::OnDoorwayAttachDoor() +{ + ASSERT(Placed_door != -1); + + AttachRoom(); + + UpdateDialog(); +} + +void CDoorwayDialog::OnDoorwayAuto() +{ + if (Current_door_room == -1) + return; + + doorway *dp = Rooms[Current_door_room].doorway_data; + + ASSERT(dp != NULL); + + int c=IsDlgButtonChecked(IDC_DOORWAY_AUTO); + + if (c) + dp->flags |= DF_AUTO; + else + dp->flags &= ~DF_AUTO; +} + +void CDoorwayDialog::OnKillfocusDoorwayPosEdit() +{ + if (Current_door_room == -1) + return; + + doorway *dp = Rooms[Current_door_room].doorway_data; + + ASSERT(dp != NULL); + + char str[100]; + + CEdit *ebox=(CEdit *) GetDlgItem(IDC_DOORWAY_POS_EDIT); + ebox->GetWindowText(str,sizeof(str)); + + dp->position = dp->dest_pos = atof(str); + + if (dp->position < 0.0) + dp->position = 0.0; + if (dp->position > 1.0) + dp->position = 1.0; + + dp->dest_pos = dp->position; + + DoorwayUpdateAnimation(&Rooms[Current_door_room]); + + World_changed = 1; +} + +void CDoorwayDialog::OnKillfocusDoorwayHitpointEdit() +{ + if (Current_door_room == -1) + return; + + doorway *dp = Rooms[Current_door_room].doorway_data; + + ASSERT(dp != NULL); + + char str[100]; + + CEdit *ebox=(CEdit *) GetDlgItem(IDC_DOORWAY_HITPOINT_EDIT); + ebox->GetWindowText(str,sizeof(str)); + + ASSERT(Objects[Cur_object_index].type == OBJ_DOOR); + + Objects[Cur_object_index].shields = atof(str); + + World_changed = 1; +} + +void CDoorwayDialog::OnDoorwayKeyAll() +{ + if (Current_door_room == -1) + return; + + doorway *dp = Rooms[Current_door_room].doorway_data; + + ASSERT(dp != NULL); + + if (IsDlgButtonChecked(IDC_DOORWAY_KEY_ALL)) + dp->flags &= ~DF_KEY_ONLY_ONE; + else + dp->flags |= DF_KEY_ONLY_ONE; + + World_changed = 1; + + UpdateDialog(); +} + +void CDoorwayDialog::OnDoorwayKeyOnlyOne() +{ + if (Current_door_room == -1) + return; + + doorway *dp = Rooms[Current_door_room].doorway_data; + + ASSERT(dp != NULL); + + if (IsDlgButtonChecked(IDC_DOORWAY_KEY_ONLY_ONE)) + dp->flags |= DF_KEY_ONLY_ONE; + else + dp->flags &= ~DF_KEY_ONLY_ONE; + + World_changed = 1; + + UpdateDialog(); +} + +void CDoorwayDialog::OnDoorwayGBIgnoreLocked() +{ + if (Current_door_room == -1) + return; + + doorway *dp = Rooms[Current_door_room].doorway_data; + + ASSERT(dp != NULL); + + int c=IsDlgButtonChecked(IDC_DOORWAY_GB_IGNORE_LOCKED); + + if (c) + dp->flags |= DF_GB_IGNORE_LOCKED; + else + dp->flags &= ~DF_GB_IGNORE_LOCKED; +} + diff --git a/editor/DoorwayDialog.h b/editor/DoorwayDialog.h new file mode 100644 index 00000000..0d81159d --- /dev/null +++ b/editor/DoorwayDialog.h @@ -0,0 +1,73 @@ +// DoorwayDialog.h : header file +// + +#include "KeypadDialog.h" +#include "gr.h" +#include "doorway.h" + +///////////////////////////////////////////////////////////////////////////// +// CDoorwayDialog dialog + +class CDoorwayDialog : public CKeypadDialog +{ +// Construction +public: + CDoorwayDialog(CWnd* pParent = NULL); // standard constructor + void UpdateKeypad(int mask); + +// Dialog Data + //{{AFX_DATA(CDoorwayDialog) + enum { IDD = IDD_DOORWAYKEYPAD }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDoorwayDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDoorwayDialog) + afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnPaint(); + virtual BOOL OnInitDialog(); + afx_msg void OnDoorwayPlaceDoorway(); + afx_msg void OnNextDoor(); + afx_msg void OnPrevDoor(); + afx_msg void OnDoorwayLocked(); + afx_msg void OnKey1Check(); + afx_msg void OnKey2Check(); + afx_msg void OnKey3Check(); + afx_msg void OnKey4Check(); + afx_msg void OnKey5Check(); + afx_msg void OnKey6Check(); + afx_msg void OnKey7Check(); + afx_msg void OnKey8Check(); + afx_msg void OnDoorwayAttachDoor(); + afx_msg void OnDoorwayAuto(); + afx_msg void OnKillfocusDoorwayPosEdit(); + afx_msg void OnKillfocusDoorwayHitpointEdit(); + afx_msg void OnDoorwayKeyAll(); + afx_msg void OnDoorwayKeyOnlyOne(); + afx_msg void OnDoorwayGBIgnoreLocked(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + virtual void OnOK(); // prevent edit controls from closing this window + +private: + void UpdateDialog(); + void DrawDoorwayDoorPic(); // draws a 3d door in the selection box. + void EnableCurrentItems(bool state); + void OnKeyCheck(int id,int keynum); + + grHardwareSurface m_DoorSurf; // surface for door display +}; diff --git a/editor/EDVARS.cpp b/editor/EDVARS.cpp new file mode 100644 index 00000000..7e38ee46 --- /dev/null +++ b/editor/EDVARS.cpp @@ -0,0 +1,188 @@ +/* + * $Logfile: /DescentIII/Main/editor/EDVARS.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:57:38 $ + * $Author: kevinb $ + * + * Misc. variables for the editor + * + * $Log: not supported by cvs2svn $ + * + * 22 9/04/98 12:29p Matt + * Added marked edge & vertex in the editor + * + * 21 6/17/98 12:30p Samir + * don't draw wireframe when moving an object. + * + * 20 6/09/98 6:11p Matt + * Removed unused variable + * + * 19 1/26/98 4:33p Samir + * Added ability to copy object ids. + * + * 18 1/21/98 12:32p Matt + * Revamped viewer system + * + * 17 1/02/98 6:38p Matt + * Got rid of Render_viewport + * + * 16 12/29/97 5:45p Samir + * Adder reference to Render viewport. + * + * 15 12/02/97 5:30p Samir + * New file dialog interface implemented. + * + * 14 12/02/97 4:43p Samir + * Repaired EDVARS.cpp + * + * 13 12/01/97 6:06p Samir + * Implemented new FileDialog tracker system. + * + * 12 9/17/97 1:01p Matt + * Ripped out segment code + * + * 11 9/17/97 11:16a Matt + * Ripped out segment code + * + * 10 9/11/97 5:38p Jason + * initial door coding for room engine + * + * 9 9/06/97 3:16p Matt + * Added current portal system + * + * 8 9/04/97 4:39p Matt + * Added includes needed as a result of removing includes from d3edit.h + * + * 7 8/29/97 5:23p Matt + * Added Placed_group + * + * 6 8/18/97 6:59p Matt + * Implemented Place Room/Attach room system + * + * 5 7/22/97 7:07p Matt + * Cleaned up D3EditState, moving some vars in and some out, and renaming + * and changing a few others + * + * 4 !/97 7:21p Matt + * Added var for current level script + * + * 13 4/02/97 8:07p Matt + * Added variable & button to toggle object move state + * + * 12 4/02/97 3:25p Jason + * got rid of WV_changed and made TV_changed update the textured view and + * flag "World_changed" + * + * 11 3/31/97 5:57p Matt + * Revamped mine update flags + * + * 10 3/31/97 3:47p Matt + * Added code to keep track of, render, and display current vertex. + * + * 9 3/17/97 12:24a Matt + * Added warning segs list + * + * 8 3/12/97 3:27p Matt + * Added scrap buffer + * + * 7 3/11/97 2:54p Samir + * Add some vars useful for rotation of segments. + * + * 6 2/28/97 6:37p Matt + * Added variable & toggle button for box selection mode + * + * 5 2/28/97 12:11p Matt + * Added vars for selected seg list + * + * 4 2/24/97 5:51p Matt + * Added vars for Markedsegp & Markedside + * + * 3 2/10/97 5:36p Matt + * Added a couple more vars + * + * 2 2/07/97 6:01p Matt + * Added Mine_changed + * +*/ + +#include "d3edit.h" +#include "room.h" + +//Current room, face, edge, & vert. +room *Curroomp=NULL; +int Curface=0,Curedge=0,Curvert=0,Curportal=-1; + +//Marked room & face +room *Markedroomp=NULL; +int Markedface=0,Markededge=0,Markedvert=0; + +//Placed room info +int Placed_door=-1; +int Placed_room=-1; +group *Placed_group = NULL; +int Placed_room_face; +float Placed_room_angle; +vector Placed_room_origin; +matrix Placed_room_orient; +matrix Placed_room_rotmat; +vector Placed_room_attachpoint; +room *Placed_baseroomp; +int Placed_baseface; + +//flags for the wireframe and textured views changed +int TV_changed=1; + +//Set this flag if a new world is loaded/created +int New_mine = 1; //init to 1 for initial redraw + +//Set this when the mine has changed +int World_changed=0; + +//Set this when the editor state (but not the world itself) has changed +int State_changed=0; + +//Set this when the viewer (i.e., player) has moved +int Viewer_moved=0; + +//Set this when the editor viewpoint has changed +int Edview_changed=0; + +//Set this when an object has moved +int Object_moved=0; + +//Vars for the list of selected rooms +int N_selected_rooms=0; +int Selected_rooms[MAX_ROOMS]; + +//Flag for if mine has changed (& thus needs to be saved) +int Mine_changed; + +//Current object +int Cur_object_index=0; + +//How does object movement work? +int Object_move_mode=REL_OBJECT; + +// The scrap buffer +group *Scrap=NULL; + +//Pointer to the scripts for this level +char *Current_level_script=NULL; + +// What mode we're currently in +int Editor_view_mode = VM_MINE; + +//The ID of the most recent viewer object (not counting room view) +int Editor_viewer_id = -1; + +// current directories for a number of file dialogs +char Current_files_dir[_MAX_PATH] = ""; +char Current_bitmap_dir[_MAX_PATH] = ""; +char Current_room_dir[_MAX_PATH] = ""; +char Current_scrap_dir[_MAX_PATH] = ""; +char Current_model_dir[_MAX_PATH] = ""; +char Current_sounds_dir[_MAX_PATH] = ""; +char Current_weapon_dir[_MAX_PATH] = ""; + +// Object ID clipboard +int Copied_object_id = 0; \ No newline at end of file diff --git a/editor/EPath.cpp b/editor/EPath.cpp new file mode 100644 index 00000000..96f03907 --- /dev/null +++ b/editor/EPath.cpp @@ -0,0 +1,597 @@ +/* + * $Logfile: /DescentIII/Main/editor/EPath.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:57:38 $ + * $Author: kevinb $ + * + * Code to create & modify paths + * + * $Log: not supported by cvs2svn $ + * + * 13 8/20/99 9:43p Gwar + * changes to InsertNodeIntoPath and DrawAllPaths for NEWEDITOR + * + * 12 8/18/99 7:00a Gwar + * changes to add EPath.cpp to NEWEDITOR project + * + * 11 4/18/99 5:42a Chris + * Added the FQ_IGNORE_RENDER_THROUGH_PORTALS flag + * + * 10 2/26/99 6:14p Matt + * Made new nodes go at the viewer position instead of in front of it, and + * make the selected path draw in a different color than the others. + * + * 9 2/26/99 12:40p Matt + * Changed occluded messages to (hopefully) be more understandable + * + * 8 2/26/99 12:26p Matt + * Fixed spelling error. + * + * 7 2/18/99 2:01p Dan + * Fixed outside/inside problem + * + * 6 2/08/99 3:29p Chris + * Added a no orient move for objects + * + * 5 2/03/99 6:56p Chris + * Added the "Move node to current object" function + * + * 4 10/14/98 2:48p Kevin + * Changed memory code to comply with mem lib + * + * 3 5/03/98 8:36p Chris + * Additional debug info + * + * 2 2/10/98 10:48a Matt + * Moved editor code from gamepath.cpp to epath.cpp + * + * 1 2/10/98 10:13a Matt + * + */ + +#include + +#ifndef NEWEDITOR + #include "d3edit.h" +#else + #include "globals.h" + #include "terrain.h" + #include "renderer.h" +#endif + +#include "epath.h" + +#include "object.h" +#include "findintersection.h" + +ubyte Show_paths = 1; + +// Allocs a gamepath that a robot will follow. Returns an index into the GamePaths +// array +int AllocGamePath () +{ + int i; + + if(Viewer_object->flags & OF_OUTSIDE_MINE) + { + OutrageMessageBox("You must be in a room or on the terrain to create a path"); + return -1; + } + + for (i=0;i= 1) + { + fvi_query fq1; + fvi_info hit_info1; + + fq1.p0 = &GamePaths[pathnum].pathnodes[nodenum - 1].pos; + fq1.startroom = GamePaths[pathnum].pathnodes[nodenum - 1].roomnum; + fq1.p1 = &hit_info.hit_pnt; + fq1.rad = 0.0f; + fq1.thisobjnum = -1; + fq1.ignore_obj_list = NULL; + fq1.flags = FQ_TRANSPOINT | FQ_IGNORE_RENDER_THROUGH_PORTALS; + + fvi_FindIntersection(&fq1, &hit_info1); + if(vm_VectorDistance(&hit_info.hit_pnt, &hit_info1.hit_pnt) > .005) + { + OutrageMessageBox("Cannot move point. There is no line of sight from the previous node to the new position."); + return -1; + } + + } + + // Check if new node is valid + if(nodenum < GamePaths[pathnum].num_nodes - 1) + { + fvi_query fq1; + fvi_info hit_info1; + + fq1.p0 = &GamePaths[pathnum].pathnodes[nodenum + 1].pos; + fq1.startroom = GamePaths[pathnum].pathnodes[nodenum + 1].roomnum; + fq1.p1 = &hit_info.hit_pnt; + fq1.rad = 0.0f; + fq1.thisobjnum = -1; + fq1.ignore_obj_list = NULL; + fq1.flags = FQ_TRANSPOINT | FQ_IGNORE_RENDER_THROUGH_PORTALS; + + fvi_FindIntersection(&fq1, &hit_info1); + if(vm_VectorDistance(&hit_info.hit_pnt, &hit_info1.hit_pnt) > .005) + { + OutrageMessageBox("Cannot move point. There is no line of sight from the next node to the new position."); + return -1; + } + } + + GamePaths[pathnum].pathnodes[nodenum].pos = hit_info.hit_pnt; + GamePaths[pathnum].pathnodes[nodenum].roomnum = hit_info.hit_room; + + return 0; +} + +// Given a path number, and a node number in that path, adds another node after the +// specified node +// Returns the index number of the new node +// If nodenum is -1, this node was not added +// roomnum is only valid if this is the first node in a room +#ifndef NEWEDITOR +int InsertNodeIntoPath (int pathnum,int nodenum,int flags) +#else +int InsertNodeIntoPath (int pathnum,int nodenum,int flags,int roomnum,vector pos,matrix orient) +#endif +{ + int i; + vector attempted_pos; + + fvi_query fq; + fvi_info hit_info; + + if(Viewer_object->flags & OF_OUTSIDE_MINE) + { + OutrageMessageBox("Error: Must be in mine or on terrain to insert a node."); + return -1; + } + + if(GamePaths[pathnum].num_nodes >= MAX_NODES_PER_PATH) + { + OutrageMessageBox("Error: Path already has its maximum amount of nodes."); + return -1; + } + + // First, move all nodes up one + for (i=GamePaths[pathnum].num_nodes-1;i>nodenum;i--) + { + memcpy (&GamePaths[pathnum].pathnodes[i+1],&GamePaths[pathnum].pathnodes[i],sizeof(node)); + } + +#ifndef NEWEDITOR + attempted_pos = Viewer_object->pos; // + Viewer_object->orient.fvec * 10.0; +#else + attempted_pos = pos; // + Viewer_object->orient.fvec * 10.0; +#endif + + +#ifndef NEWEDITOR + fq.p0 = &Viewer_object->pos; + fq.startroom = Viewer_object->roomnum; +#else + fq.p0 = &pos; + fq.startroom = roomnum; +#endif + fq.p1 = &attempted_pos; + fq.rad = 0.0f; + fq.thisobjnum = -1; + fq.ignore_obj_list = NULL; + fq.flags = FQ_TRANSPOINT | FQ_IGNORE_RENDER_THROUGH_PORTALS; + + fvi_FindIntersection(&fq, &hit_info); + + // Check if new node is valid + if(nodenum >= 0) + { + fvi_query fq1; + fvi_info hit_info1; + + fq1.p0 = &GamePaths[pathnum].pathnodes[nodenum].pos; + fq1.startroom = GamePaths[pathnum].pathnodes[nodenum].roomnum; + fq1.p1 = &hit_info.hit_pnt; + fq1.rad = 0.0f; + fq1.thisobjnum = -1; + fq1.ignore_obj_list = NULL; + fq1.flags = FQ_TRANSPOINT | FQ_IGNORE_RENDER_THROUGH_PORTALS; + + fvi_FindIntersection(&fq1, &hit_info1); + if(vm_VectorDistance(&hit_info.hit_pnt, &hit_info1.hit_pnt) > .005) + { + OutrageMessageBox("Cannot add new point. There is no line of sight from the previous node."); + return -1; + } + + } + + // Check if new node is valid + if(nodenum >= 0 && nodenum < GamePaths[pathnum].num_nodes - 1) + { + fvi_query fq1; + fvi_info hit_info1; + + fq1.p0 = &GamePaths[pathnum].pathnodes[nodenum + 1].pos; + fq1.startroom = GamePaths[pathnum].pathnodes[nodenum + 1].roomnum; + fq1.p1 = &hit_info.hit_pnt; + fq1.rad = 0.0f; + fq1.thisobjnum = -1; + fq1.ignore_obj_list = NULL; + fq1.flags = FQ_TRANSPOINT | FQ_IGNORE_RENDER_THROUGH_PORTALS; + + fvi_FindIntersection(&fq1, &hit_info1); + if(vm_VectorDistance(&hit_info.hit_pnt, &hit_info1.hit_pnt) > .005) + { + OutrageMessageBox("Cannot add new point. There is no line of sight from the next node."); + return -1; + } + } + + int newnode = nodenum + 1; + + GamePaths[pathnum].pathnodes[newnode].pos = hit_info.hit_pnt; + GamePaths[pathnum].pathnodes[newnode].roomnum = hit_info.hit_room; + +#ifndef NEWEDITOR + GamePaths[pathnum].pathnodes[newnode].fvec = Viewer_object->orient.fvec; + GamePaths[pathnum].pathnodes[newnode].uvec = Viewer_object->orient.uvec; +#else + GamePaths[pathnum].pathnodes[newnode].fvec = orient.fvec; + GamePaths[pathnum].pathnodes[newnode].uvec = orient.uvec; +#endif + + GamePaths[pathnum].num_nodes++; + + GamePaths[pathnum].pathnodes[newnode].flags = flags; + + return newnode; +} + + +// Given a pathnum and a node index, deletes that node and moves all the following nodes down +// by one +void DeleteNodeFromPath (int pathnum,int nodenum) +{ + int i; + + // First, move all nodes up one + for (i=nodenum;i=0 && n=0 && n=0;i--) + { + if (GamePaths[i].used) + return i; + } + for (i=MAX_GAME_PATHS-1;i>n;i--) + { + if (GamePaths[i].used) + return i; + } + + // this is the only one + return n; + +} + +// returns the index of the first path (from 0) alloced +// returns -1 if there are no paths +int GetFirstPath () +{ + int i; + for (i=0;inum_nodes;t++) + { + g3_RotatePoint(&rot_points[t],&gp->pathnodes[t].pos); + sort_index[t]=t; + } + +#ifndef NEWEDITOR + ddgr_color path_color = (current_path_index==D3EditState.current_path) ? GR_RGB(255,255,255) : GR_RGB(36,99,238); +#else + ddgr_color path_color = (current_path_index==Editor_state.GetCurrentPath()) ? GR_RGB(255,255,255) : GR_RGB(36,99,238); +#endif + + for (t=0;tnum_nodes-1;t++) + { + g3Point p1=rot_points[t]; + g3Point p2=rot_points[t+1]; + + g3_DrawLine (path_color,&p1,&p2); + } + + + for (t=0;tnum_nodes;t++) + { + for (int k=0;knum_nodes;k++) + { + if (rot_points[k].p3_vec.znum_nodes;t++) + { + int color; + float size; + + #ifdef NEWEDITOR + ddgr_color oldcolor; + + if (TSearch_on) + { + rend_SetPixel (GR_RGB(16,255,16),TSearch_x,TSearch_y); + oldcolor=rend_GetPixel (TSearch_x,TSearch_y); + } + #endif + +#ifndef NEWEDITOR + if (current_path_index==D3EditState.current_path && curnode == sort_index[t]) +#else + if (current_path_index==Editor_state.GetCurrentPath() && curnode == sort_index[t]) +#endif + { + color=GR_RGB (100,128,255); + size=1.2f; + } + else + { + color=GR_RGB (0,128,160); + size=1.2f; + } + + g3_DrawSphere(color,&rot_points[t],size); + + vector fpos = gp->pathnodes[sort_index[t]].pos + gp->pathnodes[sort_index[t]].fvec * (size - size/10.0); + vector upos = gp->pathnodes[sort_index[t]].pos + gp->pathnodes[sort_index[t]].uvec * (size - size/10.0); + + g3Point frot; + g3Point urot; + + g3_RotatePoint(&frot,&fpos); + g3_RotatePoint(&urot,&upos); + + g3_DrawLine (GR_RGB(0,255,0),&rot_points[t], &frot); + g3_DrawLine (GR_RGB(0,0,255),&rot_points[t], &urot); + g3_DrawSphere(GR_RGB(0,255,0),&frot,size/10.0); + g3_DrawSphere(GR_RGB(0,0,255),&urot,size/10.0); + + #ifdef NEWEDITOR + if (TSearch_on) + { + if (rend_GetPixel (TSearch_x,TSearch_y)!=oldcolor) + { + TSearch_found_type=TSEARCH_FOUND_NODE; + TSearch_seg=current_path_index; + TSearch_face=sort_index[t]; + } + } + #endif + + DrawNumber (sort_index[t] + 1,gp->pathnodes[sort_index[t]].pos,size * .5); + } + } +} + +static float ArrayX[10][20]={ {-1,1,1,-1,-1}, + {-.25, 0.0, 0.0, 0.0, -1.0, 1.0}, + {-1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0}, + {-1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -.5}, + {-1.0, -1.0, -1.0, 1.0, 1.0, 1.0}, + {-1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0}, + {-1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0}, + {-1.0, 1.0, 1.0, 1.0}, + {-1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0}, + {1.0, -1.0, -1.0, 1.0, 1.0, 1.0} + }; + +static float ArrayY[10][20]={ {1,1,-1,-1,1}, + {.75, 1.0, 1.0, -1.0, -1.0, -1.0}, + {1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, -1.0, -1.0}, + {1.0, 1.0, -1.0, -1.0, -1.0, 0, 0.0}, + {1.0, 0.0, 0.0, 0.0, 1.0, -1.0}, + {1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, -1.0, -1.0}, + {1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 0.0, 0.0, 0.0}, + {1.0, 1.0, 1.0, -1.0}, + {1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 0.0, 0.0}, + {1.0, 1.0, 0.0, 0.0, 1.0, -1.0} + }; + +static int NumOfPoints[]={5,6,10,7,6,10,10,4,10,6}; + +void DrawNumber (int num,vector pos,float size) +{ + g3Point basepnt,rot_pnt[20]; + int num_array[10]; + int i,j; + int total = num; + size/=2; + + if(num < 0) + { + return; + } + + int num_numbers = log10(num) + 1; + if (num_numbers > 10) + { + mprintf((0, "Cannot represent a number with over 10 digits\n")); + Int3(); + return; + } + + for(j = num_numbers - 1; j >= 0; j--) + { + num_array[j] = total / (pow(10, j)); + total -= num_array[j] * pow(10,j); + } + + for(j = 0; j < num_numbers; j++) + { + vector cur_pos; + + if (num_numbers & 0x00000001) + cur_pos = pos + (2.1 * size * ((num_numbers >> 1) - j)) * Viewer_object->orient.rvec; + else + cur_pos = pos + (2.1 * size * ((num_numbers >> 1) - j) - size) * Viewer_object->orient.rvec; + + g3_RotatePoint (&basepnt,&cur_pos); + + for (i=0;iGetWindowText(m_EditBuf); + CDialog::OnOK(); +} + +BOOL CEditLineDialog::OnInitDialog() +{ + CEdit *edit_ctl = (CEdit *)GetDlgItem(IDC_EDIT); + + CDialog::OnInitDialog(); + + SetWindowText(m_Title); + + ((CEdit *) GetDlgItem(IDC_PROMPT))->SetWindowText(m_Caption); + + if (m_Initial) + edit_ctl->SetWindowText(m_Initial); + + //Turn on/off numeric-only input + if (m_Numeric) + edit_ctl->ModifyStyle(0,ES_NUMBER); + else + edit_ctl->ModifyStyle(ES_NUMBER,0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +//Gets a string from the user +//Parameters: buf - buffer the string is written to. should be initialized to default value +// maxsize - the length of buf +// title - the title for the input window +// prompt - the prompt for the input box +//Returns: false if cancel was pressed on the dialog, else true +// If false returned, buf is unchanged +bool InputString(char *buf,int maxsize,char *title,char *prompt,CWnd *wnd) +{ + CEditLineDialog dlg(title,prompt,buf,0,wnd); + + if (dlg.DoModal() == IDOK) { + strncpy(buf,(char *) dlg.GetText(),maxsize); + buf[maxsize-1] = 0; //strncpy doesn't terminate if string is too long + return 1; + } + else + return 0; +} + +//Gets a number from the user +//Parameters: n - filled in the with return value +// title - the title for the input window +// prompt - the prompt for the input box +//Returns: false if cancel was pressed on the dialog, else true +// If false returned, n is unchanged +bool InputNumber(int *n,char *title,char *prompt,CWnd *wnd) +{ + char buf[100] = ""; + CEditLineDialog dlg(title,prompt,buf,1,wnd); + + if (dlg.DoModal() == IDOK) { + *n = atoi((char *) dlg.GetText()); + return 1; + } + else + return 0; +} + + diff --git a/editor/EditLineDialog.h b/editor/EditLineDialog.h new file mode 100644 index 00000000..896d5676 --- /dev/null +++ b/editor/EditLineDialog.h @@ -0,0 +1,70 @@ +// EditLineDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CEditLineDialog dialog + +class CEditLineDialog : public CDialog +{ +// Construction +public: + CEditLineDialog(char *caption, char *title, char *initial, bool numeric, CWnd* pParent); // standard constructor + CEditLineDialog(char *caption, CWnd* pParent); // standard constructor + +// Dialog Data + //{{AFX_DATA(CEditLineDialog) + enum { IDD = IDD_EDITLINEDLG }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CEditLineDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CEditLineDialog) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +private: + CString m_EditBuf; +// char m_Caption[64]; + int size; + char *m_Buffer; + char *m_Caption; + char *m_Initial; + char *m_Title; + + bool m_Numeric; //flag for whether this is numeric + + +public: +// returns a pointer to the inputted text. + LPCSTR GetText() const { return (LPCSTR)m_EditBuf; }; +}; + +//Gets a string from the user +//Parameters: buf - buffer the string is written to. should be initialized to default value +// maxsize - the length of buf +// title - the title for the input window +// prompt - the prompt for the input box +//Returns: false if cancel was pressed on the dialog, else true +// If false returned, buf is unchanged +bool InputString(char *buf,int maxsize,char *title,char *prompt,CWnd *wnd = NULL); + +//Gets a number from the user +//Parameters: n - filled in the with return value +// title - the title for the input window +// prompt - the prompt for the input box +//Returns: false if cancel was pressed on the dialog, else true +// If false returned, n is unchanged +bool InputNumber(int *n,char *title,char *prompt,CWnd *wnd = NULL); diff --git a/editor/Erooms.cpp b/editor/Erooms.cpp new file mode 100644 index 00000000..be8d9a00 --- /dev/null +++ b/editor/Erooms.cpp @@ -0,0 +1,3383 @@ +/* + * $Logfile: /DescentIII/Main/editor/Erooms.cpp $ + * $Revision: 1.1.1.1 $ + * $Date: 2003-08-26 03:57:38 $ + * $Author: kevinb $ + * + * Functions to create, delete, etc. rooms + * + * $Log: not supported by cvs2svn $ + * + * 167 10/14/99 4:21p Matt + * Added code to remove duplicate faces from a room. + * + * 166 9/30/99 5:02p Matt + * Automatically normalize face UV values when a level is verified. + * + * 165 9/07/99 4:36p Gwar + * disabled deletion of only the face verts of a face in DeleteRoomFace + * (it now deletes all unused verts, like before) + * + * 164 8/30/99 1:50p Gwar + * stupid me forgot a semicolon + * + * 163 8/30/99 1:23p Gwar + * In DeleteRoomFace, added a way to delete only verts that were in the + * deleted face + * + * 162 8/17/99 6:11p Gwar + * handle NEWEDITOR texture management in CopyRoom + * + * 161 8/15/99 3:10a Gwar + * decrement Curface in DeleteRoomFace if Curface is the last face in the + * room + * + * 160 8/13/99 4:52p Gwar + * fixed a stupid bug from my last checkin + * + * 159 8/13/99 4:43p Gwar + * decrement Markedface in DeleteRoomFace if Markedface is the last face + * in the room + * + * 158 7/17/99 1:36a Gwar + * fixed a string formatting bug in a call to OutrageMessageBox + * + * 157 7/14/99 9:07a Gwar + * added a parameter to AllocLoadRoom + * + * 156 7/06/99 10:22a Gwar + * removed and #ifdef NEWEDITOR for this build... + * + * 155 7/04/99 4:55p Gwar + * changes for texture management in NEWEDITOR + * + * 154 7/03/99 5:50p Gwar + * minor changes for NEWEDITOR + * + * 153 7/02/99 2:17p Gwar + * added a parameter to AllocLoadRoom to disable centering on origin + * + * 152 5/05/99 5:03a Gwar + * renamed ned_GameTextures array to GameTextures in new editor to make + * game code happy; 3D texture view still does not display textures + * + * 151 5/05/99 3:02a Gwar + * added a parameter to DeleteRoomFace (by permission) + * + * 150 4/30/99 2:21p Jason + * changes to verify level completeness + * + * 149 4/27/99 3:36p Jason + * fixed terrain occlusion bug + * + * 148 4/26/99 11:11a Chris + * Updated Bnode system + * + * 147 4/25/99 10:16p Matt + * Added soundsource check to verify mine. + * + * 146 4/25/99 9:02p Chris + * Improving the Bnode system + * + * 145 4/21/99 10:20p Matt + * Don't compute shells for external rooms in mine verify. + * + * 144 4/21/99 5:15a Gwar + * added support for paletted rooms (ORFs) into new editor + * + * 143 4/20/99 8:19p Matt + * Added an assert. + * + * 142 4/15/99 3:10p Matt + * Took out Int3() in FindSharedEdge(), and took out some mrpintf()s in + * the shell calculation. + * + * 141 4/12/99 10:43a Jason + * checked in so code would compile + * + * 140 4/10/99 5:38p Matt + * Commented out some code that wouldn't compile. + * + * 139 4/08/99 5:46p Jason + * added texture finding option + * + * 138 4/08/99 3:15p Matt + * Don't compute a shell for external rooms. + * + * 137 4/08/99 12:45p Jason + * don't count lights or non renderable portal faces in the level + * + * 136 4/07/99 2:22p Jason + * warned designers if they have over 60 128s in their level + * + * 135 4/07/99 12:43p Jason + * added texture counting to verify level + * + * 134 4/07/99 11:24a Jason + * verify level now checks terrain occlusion and boa + * + * 133 4/06/99 5:10p Matt + * Base room shell on all portals in the room, not just the first one. + * + * 132 4/05/99 11:17a Matt + * Added code to list all the objects in the levels. + * + * 131 4/01/99 9:42a Matt + * Added code to compute room shells, and made verify level do it. + * + * 130 3/31/99 11:34a Matt + * Got rid of unused forcefield checkbox on room tab + * + * 129 3/31/99 11:33a Matt + * Make note of non-planar faces that are portals. + * + * 128 3/30/99 7:57p Matt + * Added prototype and moved a function to be inline in the header. + * + * 127 3/30/99 7:20p Matt + * Deleted PointsAreColinear(), since it was never used and worked the + * wrong way. + * + * 126 3/29/99 6:45p Matt + * Changed concavity tolerance from 0.005 to 0.05. + * Added verify code to check for concave faces and degenerate faces. + * Added code to fix degenerate faces. + * + * 125 3/24/99 5:53p Jason + * added per room ambience settings + * + * 124 3/23/99 1:41p Jason + * fixed concave normal bug + * + * 123 3/11/99 5:12p Matt + * Added some error messages for the new verify level checks + * + * 122 3/11/99 4:58p Matt + * Fixed extra-stupid malloc bug + * + * 121 3/11/99 3:20p Matt + * Added checks for T-joints and mismatched portals to verify level. + * + * 120 2/19/99 1:24p Matt + * Moved ComputerCenterRoomOnFace() from editor to main + * + * 119 2/18/99 12:32p Jason + * added room multiplier + * + * 118 2/11/99 1:44p Matt + * Fix up triggers when deleting a face + * + * 117 2/03/99 1:10p Matt + * Changed the paletted room current faces to be stored in a seperate + * array, instead of in the room structure. + * + * 116 1/29/99 12:48p Matt + * Rewrote the doorway system + * + * 115 1/25/99 7:39p Luke + * Added comment to tell me when ROOMFILE_VERSION changes (so I can change + * RoomView) + * + * 114 1/21/99 11:34a Matt + * Got rid of portal triggers. Since we don't have multi-face portals, a + * face trigger works fine for a portal. Also fixed a few editor/trigger + * bugs. + * + * 113 12/22/98 2:03p Matt + * Added room names, and made rooms not compress so that room numbers are + * suitable for persistant uses. + * + * 112 12/09/98 3:12p Jason + * save/load light multiples with faces + * + * 111 12/07/98 12:00p Sean + * Adjusted co-planar epsilon + * + * 110 11/17/98 5:58p Sean + * Changed concavity tolerance from 0.0001 to 0.0005 (MattT on Sean's + * machine) + * + * 109 11/03/98 6:20p Matt + * Changed the concavity check to not be dependent on the length of the + * edges being checked. + * + * 108 11/02/98 6:15p Chris + * Room AABBs get saved with the level and the sort_face and dec_sort_face + * list s have been removed + * + * 107 11/01/98 1:58a Jeff + * converted the vsprintf calls to use the Pvsprintf, which is a safe + * vsprintf, no buffer overflows allowed + * + * 106 10/08/98 8:16p Matt + * Made AssignDefaultUVsToRoom() call AssignDefaultUVsToRoomFace() + * + * 105 10/08/98 4:23p Kevin + * Changed code to comply with memory library usage. Always use mem_malloc + * , mem_free and mem_strdup + * + * 104 10/07/98 12:48p Matt + * Added some extra error checking to prevent doubly-formed portals. + * + * 103 10/03/98 8:05p Matt + * Changed the way CheckIfFaceIsPlanar() works (& renamed it to + * FaceIsPlanar()) and added planar check to VerifyMine() & VerifyRoom() + * + * 102 9/29/98 4:00p Matt + * Fix selected room list when compressing the mine. + * + * 101 9/28/98 10:55a Jason + * fixed some bugs that VC6 caught + * + * 100 9/24/98 5:00p Matt + * Improved error checking for running out of rooms. + * + * 99 9/14/98 12:18p Matt + * Took out mprintf() that was slowing down room importing. + * + * 98 9/10/98 6:37p Matt + * Increased concavity check tolerance (from 0.002 to 0.003) to fix + * problem forming smooth bridge on Dan's level 9. + * + * 97 9/09/98 9:10p Matt + * In verify & fix functions, don't process non-used rooms. + * + * 96 9/08/98 6:12p Matt + * Added code to check for and fix duplicate and unused points. + * + * 95 9/08/98 12:54p Matt + * Changed CONCAVITY_TOLERANCE from 0.0000000001 to 0.002 to fix a problem + * Sean was having joining faces. + * + * 94 9/08/98 12:53p Matt + * Added duplicate point check to level verify + * + * 93 9/08/98 12:05p Jason + * moved doorway.h out of room.h + * + * 92 9/03/98 1:23p Matt + * Made AddVertToFace() compute alpha, u2, & v2 values for the new point. + * + * 91 9/02/98 5:56p Matt + * Changed comment + * + * 90 9/02/98 4:20p Matt + * Cleaned up some linking code now that we don't have multi-face portals. + * + * 89 9/02/98 2:28p Matt + * New function to add a vertex to a face. + * + * 88 9/01/98 12:04p Matt + * Ripped out multi-face portal code + * + * 87 8/31/98 4:37p Matt + * Added improved room & mine error checking. + * + * 86 8/14/98 4:46p Matt + * Fix doorways when compressing the mine + * + * 85 8/11/98 12:46p Matt + * Temporary fix for forming portals between faces with different numbers + * of vertices. + * + * 84 7/21/98 4:25p Chris + * Fixed a bug with the new AABB stuff + * + * 83 7/21/98 2:14p Chris + * Some FVI speedups - not done + * + * 82 7/17/98 9:56a Chris + * Intermediate checkin + * + * 81 7/16/98 8:29p Chris + * Partial implementation of the new collide code + * + * 80 6/26/98 12:30p Matt + * In PointsAreSame(), check for the middle point being the same as either + * of the end points. + * + * 79 6/25/98 7:15p Matt + * Added code to check for errors in portal linkage + * + * 78 6/19/98 12:22p Jason + * fixed special faces bug + * + * 77 6/08/98 12:27p Matt + * Added function to copy from one face to another the flags that should + * be inherited. + * + * 76 6/02/98 6:03p Jason + * added specular lightmaps + * + * 75 5/25/98 3:46p Jason + * added better light glows + * + * 74 5/22/98 3:28p Jason + * added specular lighting + * + * 73 5/04/98 12:27p Matt + * Fixed misspelling + * + * 72 4/27/98 6:41p Matt + * Cleaned up epsilons some more, and moved some code here from hroom.cpp. + * + * 71 4/21/98 4:05p Jason + * made copyface take into accound light multiples + * + * 70 4/21/98 2:44p Matt + * Added code to check a level, but haven't finished or made it available + * yet. + * + * 69 4/16/98 3:33p Matt + * Cleaned up epsilon values, again. + * + * 68 4/16/98 12:59p Matt + * Changed point-to-edge epsilon, and took out Int3s's + * + * 67 4/16/98 10:41a Matt + * Added FindSharedEdgeAcrossRooms() + * + * 66 4/15/98 4:57p Matt + * Fixed massive stupidity in the way I computed if a point was outside an + * edge for polygon:polygon clipping. + * + * 65 4/02/98 12:23p Jason + * trimmed some fat from our structures + * + * 64 3/31/98 3:49p Jason + * added memory lib + * + * 63 3/18/98 4:31p Chris + * Speed up fvi and fixed some bugs + * + * 62 3/16/98 5:50p Chris + * Added sorted face lists for fvi + * + * 61 2/24/98 1:54p Jason + * added much stricter concavity testing + * + * 60 2/23/98 4:25p Jason + * got rid of stupid compiler warning + * + * 59 2/22/98 3:02p Jason + * changed concavity tolerance in CheckIfFaceIsPlanar + * + * 58 2/19/98 2:20p Jason + * fixed lightmap combining to eliminate tjoint problems + * + * 57 2/16/98 1:07p Matt + * Changed assert to int3 + * + * 56 2/12/98 9:10p Matt + * Adjusted epsilon when clipping rooms. + * + * 55 2/11/98 4:03p Matt + * When loading a room, center it at the origin + * + * 54 2/11/98 12:38p Matt + * Fixed small bug in DeleteRoomVert() + * + * 53 2/10/98 3:50p Jason + * added pulsing walls + * + * 52 2/08/98 6:03p Matt + * When copying a face, don't copy the has_trigger flag + * + * 51 1/20/98 4:05p Matt + * Move BuildListOfPortalVerts() from roomkeypaddialog.cpp to erooms.cpp + * + * 50 1/16/98 11:53a Matt + * Relaxed low-precision normal check, and added mprintfs with info on + * problem normals + * + * 49 1/15/98 7:34p Matt + * Revamped error checking when computing face normals + * + * 48 1/12/98 5:05p Luke + * Code was using wrong constant when searching palette rooms (MattT on + * Luke's machine) + * + * 47 12/30/97 3:33p Jason + * fixed stupid variable bug + * + * 46 11/24/97 1:30a Jason + * first attempt at adding shadows + * + * 45 11/17/97 7:37p Sean + * Increased point edge epsilon (Matt on Sean's machine) + * + * 44 11/11/97 6:45p Matt + * Adjusted epsilon value for edge clip + * + * 43 11/04/97 7:30p Matt + * Dealt with yet more precision problems in room clip + * + * 42 10/30/97 6:31p Jason + * fixed potential lightmap bugs + * + * 41 10/29/97 12:36p Matt + * Dealt with some precision problems in clipper + * + * 40 10/13/97 5:08p Matt + * Moved ComputeRoomBoundingSphere() & CreateRoomObjects() from editor to + * main + * + * + * 39 10/01/97 7:51p Matt + * Added code for external rooms + * + * 38 9/24/97 3:20p Matt + * Added ComputeRoomMinMax() + * + * 37 9/19/97 2:52p Jason + * changes to fix lightmap seam problem + * + * 36 9/17/97 11:52a Samir + * BIG SEGMENT RIPOUT + * + * 35 9/16/97 4:27p Matt + * Got rid of static_light & changed fields in the room struct + * + * 34 9/15/97 2:21p Matt + * Remap triggers when compress mine. (Also deleted some segment engine + * code.) + * + * 33 9/15/97 11:03a Jason + * fixed bug with alpha + * + * 32 9/12/97 2:27p Matt + * Added code to delete any unused vertices when deleting a face + * + * 31 9/10/97 3:02p Matt + * Moved GetIJ() from erooms.cpp to room.cpp + * + * 30 9/09/97 10:25a Matt + * Clip alpha values when clipping edge + * + * 29 9/03/97 2:00p Jason + * made LIGHTMAP_SPACING #define for controlling spacing of lightmap + * elements + * + * 28 9/02/97 5:17p Jason + * changes for dynamic lighting + * + * 27 9/02/97 2:28p Matt + * Changed PointOutsideEdge() to the more generally-useful + * CheckPointAgainstEdge() + * Made CopyFace() clear the portal number + * + * 26 9/02/97 11:47a Jason + * Got alpha per vertex working + * + * 25 9/02/97 11:01a Matt + * Moved assert() + * + * 24 8/29/97 5:44p Matt + * Moved a couple functions from hroom.cpp, and added a couple more useful + * functions. + * + * 23 8/28/97 12:31p Jason + * added hi-res lightmaps for radiosity + * + * 22 8/22/97 1:02p Matt + * Got CompressMine() working for rooms + * + * 21 8/21/97 5:56p Matt + * Added a bunch of useful functions, and make CheckFaceConcavity() more + * generally useful. + * + * 20 8/18/97 11:47a Sean + * FROM JASON: Recompute normals on LoadRoom + * + * 19 8/04/97 6:46p Jason + * added code for a lightmap system + * + * 18 8/01/97 6:11p Matt + * Added several functions that I needed for attach room code + * + * 17 8/01/97 4:41p Jason + * made FixConcaveFaces reset all room normals as an extra precaution + * + * 16 8/01/97 12:50p Jason + * added code to support scaling of rooms/faces/edges + * + * 15 7/31/97 3:31p Jason + * added functions to rotate portal rooms + * + * 14 7/29/97 1:54p Matt + * Added some generally useful room/face functions + * + * 13 7/21/97 12:14p Matt + * Fixed stupid bug in concavity check + * + * 12 7/18/97 5:36p Jason + * save changed paletted rooms on exit + * + * 11 7/18/97 4:37p Matt + * Added function CheckFaceConcavity() + * + * + * + * $NoKeywords: $ + */ + + +#include +#include + +#ifndef NEWEDITOR +#include "d3edit.h" +#else +#include "..\neweditor\stdafx.h" +#include "..\neweditor\neweditor.h" +#include "..\neweditor\globals.h" +#include "..\neweditor\ned_geometry.h" +#endif + +#include "erooms.h" +#include "room.h" +#include "gametexture.h" +#include "terrain.h" +#include "special_face.h" +#include "lighting.h" +#include "trigger.h" +#include "mem.h" +#include "doorway.h" +#include "pstring.h" + +#ifndef NEWEDITOR +#include "editor_lighting.h" +#endif + +#include "boa.h" +#include "bnode.h" + +//List of current faces for the palette rooms +int Current_faces[MAX_PALETTE_ROOMS]; + +//Returns a free room number, & marks it no longer free. Returns -1 if none free. +//If palette_room is true, allocate out of the part of the array for the room palette +int GetFreeRoom(bool palette_room) +{ + int roomnum; + int start,end; + + int old_hri = Highest_room_index; + + if (palette_room) { + start = FIRST_PALETTE_ROOM; + end = start+MAX_PALETTE_ROOMS; + } + else { + start = 0; + end = MAX_ROOMS; + } + + for (roomnum=start;roomnum Highest_room_index) + Highest_room_index = roomnum; + } + else + Current_faces[roomnum - FIRST_PALETTE_ROOM] = 0; + + BNode_RemapTerrainRooms(old_hri, Highest_room_index); + + return roomnum; +} + +//Allocates a room & initializes it. +//Memory is allocated for faces & verts arrays, but the elements are *not* initialized +//The number of portals is set to zero. +//If palette_room is true, allocate out of the part of the array for the room palette +//Returns: pointer to new room, or NULL if no free rooms +room *CreateNewRoom(int nverts,int nfaces,bool palette_room) +{ + int roomnum; + room *rp; + + //Get a free room + roomnum = GetFreeRoom(palette_room); + + if (roomnum == -1) + return NULL; + + rp = &Rooms[roomnum]; + + //Initalize room, allocating memory + InitRoom(rp,nverts,nfaces,0); + + return rp; +} + + +// Find the uv associated with a face vertex +// This routine works by projecting the face on to its own normals plane +// and just treating the face like a 2d surface + +// Important - vertnum is the index into the face_verts[] array in the face structure, +// not an index into the verts[] array of the room structure +void GetUVLForRoomPoint (int roomnum,int facenum,int vertnum,roomUVL *uvl) +{ + matrix face_matrix,trans_matrix; + vector fvec; + vector avg_vert; + vector verts[MAX_VERTS_PER_FACE]; + vector rot_vert; + + ASSERT (Rooms[roomnum].used); + ASSERT (Rooms[roomnum].faces[facenum].num_verts>=3); + + // find the center point of this face + vm_MakeZero (&avg_vert); + for (int i=0;itopmost_y) + { + topmost_point=i; + topmost_y=verts[i].y; + } + } + + ASSERT (topmost_point!=-1); + + // Find right most point + int rightmost_point=-1; + float rightmost_x=-900000.00f; // a big number + + for (i=0;irightmost_x) + { + rightmost_point=i; + rightmost_x=verts[i].x; + } + } + + ASSERT (rightmost_point!=-1); + + // Find bottom most point + int bottommost_point=-1; + float bottommost_y=900000.0f; // a big number + + for (i=0;iu=(verts[vertnum].x-base_vector.x)/20.0; + uvl->v=(base_vector.y-verts[vertnum].y)/20.0; +} + +#define DEFAULT_ALPHA 255 + +// Goes through each face of the passed room and sets the default uvs +void AssignDefaultUVsToRoom (room *rp) +{ + ASSERT (rp->used>=1); + + for (int i=0;inum_faces;i++) + AssignDefaultUVsToRoomFace(rp,i); +} + +// Sets the default UVS for a room face +void AssignDefaultUVsToRoomFace (room *rp,int facenum) +{ + ASSERT (rp->used>=1); + ASSERT (facenumnum_faces); + + int t; + + for (t=0;tfaces[facenum].num_verts;t++) + { + GetUVLForRoomPoint (ROOMNUM(rp),facenum,t,&rp->faces[facenum].face_uvls[t]); + rp->faces[facenum].face_uvls[t].alpha = DEFAULT_ALPHA; + } + +} + + +// Searches thru all rooms for a specific name, returns -1 if not found +// or index of room with name +int FindRoomName (char *name) +{ + int i; + + ASSERT (name!=NULL); + + for (i=FIRST_PALETTE_ROOM;inum_verts;i++) + { + rp->verts[i].x=cf_ReadFloat (infile); + rp->verts[i].y=cf_ReadFloat (infile); + rp->verts[i].z=cf_ReadFloat (infile); + } + break; + case ROOM_TEXTURE_CHUNK: + if (!initted) + { + Int3(); // bad format info, get jason + done=1; + break; + } + highest_index=cf_ReadInt (infile); + for (i=0;inum_faces;i++) + { + ubyte light_multiple=4; + if (room_version>=4) + light_multiple=cf_ReadByte(infile); + + int nverts = cf_ReadInt (infile); + + //rp->faces[i].num_verts=cf_ReadInt (infile); + //rp->faces[i].face_verts=(short *)mem_malloc (sizeof(short)*rp->faces[i].num_verts); + //rp->faces[i].face_uvls=(g3UVL *)mem_malloc (sizeof(g3UVL)*rp->faces[i].num_verts); + + InitRoomFace(&rp->faces[i],nverts); + + ASSERT (rp->faces[i].face_verts); + ASSERT (rp->faces[i].face_uvls); + + + rp->faces[i].normal.x=cf_ReadFloat (infile); + rp->faces[i].normal.y=cf_ReadFloat (infile); + rp->faces[i].normal.z=cf_ReadFloat (infile); + rp->faces[i].light_multiple=light_multiple; + + tex_index=cf_ReadShort (infile); + tex_index=FindTextureName (texture_names[tex_index]); + + if (tex_index==-1) // If this texture doesn't exist, bash to error texture + rp->faces[i].tmap=0; + else + rp->faces[i].tmap=tex_index; + + for (int t=0;tfaces[i].num_verts;t++) + { + rp->faces[i].face_verts[t]=cf_ReadShort (infile); + rp->faces[i].face_uvls[t].u=cf_ReadFloat (infile); + rp->faces[i].face_uvls[t].v=cf_ReadFloat (infile); + cf_ReadFloat (infile); + cf_ReadFloat (infile); + cf_ReadFloat (infile); + cf_ReadFloat (infile); + if (room_version>=1) + rp->faces[i].face_uvls[t].alpha=Float_to_ubyte(cf_ReadFloat (infile)); + + if (room_version<=1) + rp->faces[i].face_uvls[t].alpha=255; + } + } + break; + case ROOM_END_CHUNK: + done=1; + break; + default: + // skip the ones we don't know + for (i=0;inum_verts;v++) + rp->verts[v] -= center; + } + + //We're done + return ROOMNUM(rp); +} + +// Gets next palette room (from n) that has actually been alloced +int GetNextRoom (int n) +{ + int i; + + ASSERT ((n==-1) || ((n>=FIRST_PALETTE_ROOM) && n and . Let's see if we have a concavity + dot = (-j0 * i1) + (i0 * j1); + dot /= sqrt(i0*i0 + j0*j0) * sqrt(i1*i1 + j1*j1); + + if (dot > CONCAVITY_TOLERANCE) { //we have a concavity! + //mprintf((0,"Concavity check dot = %f\n",dot)); + return vn; //..so return this vertex number + } + } + + //No concavity found + return -1; +} + +//Recompute the surface normals for all the faces in a room +//Parameters: rp - pointer to the room +//Returns: true if normals computed ok, false if some normals were bad +bool ResetRoomFaceNormals(room *rp) +{ + int bad_normals = 0; + + for (int i=0;inum_faces;i++) + if (! ComputeFaceNormal(rp,i)) + bad_normals++; + + if (bad_normals > 0) { + mprintf((1,"Warning: Room %d has %d bad or low-precision normals\n",ROOMNUM(rp),bad_normals)); + return 0; + } + else + return 1; +} + + +//Copies the contents of one face to another. Sets the portal num in the new face to -1. +//Parameters: dfp - pointer to the destination face. This face should be uninitialized. +// sfp - pointer to the source face +void CopyFace(face *dfp,face *sfp) +{ + InitRoomFace(dfp,sfp->num_verts); + + dfp->flags = sfp->flags; + dfp->portal_num = -1; + dfp->normal = sfp->normal; + dfp->tmap = sfp->tmap; + dfp->light_multiple = sfp->light_multiple; + + // Clear the flags that we don't want transferred over + dfp->flags &= ~FF_LIGHTMAP; + dfp->flags &= ~FF_HAS_TRIGGER; + + //Copy vertices and uvls + for (int i=0;inum_verts;i++) { + dfp->face_verts[i] = sfp->face_verts[i]; + dfp->face_uvls[i] = sfp->face_uvls[i]; + } +} + +//Checks to see if a face is planar. +//See if all the points are within a certain distance of an average point +//Returns 1 if face is planar, 0 if not +bool FaceIsPlanar(int nv,short *face_verts,vector *normal,vector *verts) +{ + //Triangles are always planar + if (nv == 3) + return 1; + + //Get average distance from origin for points on this face + float average_d=0; + for (int v=0;v POINT_TO_PLANE_EPSILON) + return 0; + } + + //Didn't find anything wrong, so face is planar + return 1; +} + +// Fixes all the concave/nonplanar faces of facelist of room rp +void FixConcaveFaces (room *rp,int *facelist,int facecount) +{ + int i,t,k; + face *newfaces; + + for (i=0;inum_faces; + int concave_count=rp->faces[facelist[i]].num_verts; + int old_tmap=rp->faces[facelist[i]].tmap; + int num_new_faces=concave_count-3; + ASSERT (num_new_faces>0); + + mprintf ((0,"Creating %d new faces from face %d!\n",num_new_faces,facelist[i])); + + // copy the concave vert indices for later use + for (t=0;tfaces[facelist[i]].face_verts[t]; + + // Allocate memory for our new faces + int nfaces=rp->num_faces+num_new_faces; + + newfaces = (face *) mem_malloc(nfaces * sizeof(face)); + ASSERT(newfaces != NULL); + + // Copy all the faces into our new array + for (t=0;tnum_faces;t++) + { + + if (t!=facelist[i]) + { + int nverts=rp->faces[t].num_verts; + + newfaces[t].face_verts = (short *) mem_malloc(nverts * sizeof(short)); + ASSERT(newfaces[t].face_verts != NULL); + newfaces[t].face_uvls = (roomUVL *) mem_malloc(nverts * sizeof(roomUVL)); + ASSERT(newfaces[t].face_uvls != NULL); + + newfaces[t].normal=rp->faces[t].normal; + newfaces[t].tmap=rp->faces[t].tmap; + newfaces[t].flags=rp->faces[t].flags; + newfaces[t].portal_num=rp->faces[t].portal_num; + newfaces[t].num_verts=rp->faces[t].num_verts; + newfaces[t].special_handle=BAD_SPECIAL_FACE_INDEX; + + for (k=0;kfaces[t].face_verts[k]; + newfaces[t].face_uvls[k]=rp->faces[t].face_uvls[k]; + } + } + else // special case the concave face into a triangle + { + int nverts=3; + + newfaces[t].face_verts = (short *) mem_malloc(nverts * sizeof(short)); + ASSERT(newfaces[t].face_verts != NULL); + newfaces[t].face_uvls = (roomUVL *) mem_malloc(nverts * sizeof(roomUVL)); + ASSERT(newfaces[t].face_uvls != NULL); + + newfaces[t].tmap=rp->faces[t].tmap; + newfaces[t].flags=rp->faces[t].flags; + newfaces[t].portal_num=rp->faces[t].portal_num; + newfaces[t].num_verts=3; + newfaces[t].special_handle=BAD_SPECIAL_FACE_INDEX; + + for (k=0;kfaces[t].face_verts[k]; + newfaces[t].face_uvls[k]=rp->faces[t].face_uvls[k]; + } + + // Get new normal + if (! ComputeFaceNormal(rp,t)) + Int3(); //Bad normal: get Matt or Jason, or ignore. + + newfaces[t].normal=rp->faces[t].normal; + + + } + } + + // Free up the old list of faces + mem_free (rp->faces); + rp->faces=newfaces; + rp->num_faces=nfaces; + + if(rp->num_bbf_regions) + { + for(i = 0; i < rp->num_bbf_regions; i++) + { + mem_free(rp->bbf_list[i]); + } + mem_free(rp->bbf_list); + mem_free(rp->num_bbf); + mem_free(rp->bbf_list_min_xyz); + mem_free(rp->bbf_list_max_xyz); + mem_free(rp->bbf_list_sector); + rp->num_bbf_regions = 0; + } + + // Now build the remaining triangles of our concave face + for (t=0;tfaces[old_num_faces+t],3); + + for (t=0;tfaces[old_num_faces+t].face_verts[0]=concave_verts[0]; + rp->faces[old_num_faces+t].face_verts[1]=concave_verts[2+t]; + rp->faces[old_num_faces+t].face_verts[2]=concave_verts[3+t]; + rp->faces[old_num_faces+t].tmap=old_tmap; + + if (! ComputeFaceNormal(rp,old_num_faces+t)) + Int3(); //Bad normal: get Matt or Jason, or ignore. + + AssignDefaultUVsToRoomFace (rp,old_num_faces+t); + + } + } + } + + if (! ResetRoomFaceNormals(rp)) + Int3(); //Get Matt or Jason +} + +//Changes the number of verts in a face. Frees and reallocates the face_verts & face_uvls arrays. +//Leaves all other fields the same +void ReInitRoomFace(face *fp,int nverts) +{ + ASSERT(nverts != 0); + + fp->num_verts = nverts; + + mem_free(fp->face_verts); + mem_free(fp->face_uvls); + + fp->face_verts = (short *) mem_malloc(nverts * sizeof(*fp->face_verts)); ASSERT(fp->face_verts != NULL); + fp->face_uvls = (roomUVL *) mem_malloc(nverts * sizeof(*fp->face_uvls)); ASSERT(fp->face_uvls != NULL); +} + +//Determines if two points are close enough together to be considered the same +//Parameters: v0,v1 - the two points +//Returns: true if the points are the same or very close; else false +bool PointsAreSame(vector *v0,vector *v1) +{ + float d = vm_VectorDistance(v0,v1); + + return (d < POINT_TO_POINT_EPSILON); +} + +//Check to see if a point is in, in front of, or behind a plane +//Parameters: checkpoint - the point to check +// planepoint,normal - the plane we're checking against +//Returns: 0 if on the plane, -1 if behind, 1 if in front +int CheckPointToPlane(vector *checkpoint,vector *planepoint,vector *normal) +{ + float d = (*checkpoint - *planepoint) * *normal; + + if (d < -POINT_TO_PLANE_EPSILON) + return -1; + else if (d > POINT_TO_PLANE_EPSILON) + return 1; + else + return 0; +} + +//Check to see if all the points on a face are in front of a plane +//Parameters: rp,facenum - the face to check +// planepoint,normal - define the plane we're checking against +//Returns: the number of the first point found on the back of the plane, or -1 of all on front +int CheckFaceToPlane(room *rp,int facenum,vector *planepoint,vector *normal) +{ + face *fp = &rp->faces[facenum]; + + for (int i=0;inum_verts;i++) + if (CheckPointToPlane(&rp->verts[fp->face_verts[i]],planepoint,normal) < 0) + return i; + + return -1; //no points found behind the plane +} + +//Create space for additional vertices in a room. +//Allocates a new array of vertices, copies from the old list, and frees the old list +//The new vertices are at the end of the list, so none of the old vertices change number +//Parameters: rp - the room +// n_new_verts - how many vertices are being added to the room +//Returns: the number of the first new vertex +int RoomAddVertices(room *rp,int num_new_verts) +{ + if (num_new_verts == 0) + return 0; + + vector *newverts = (vector *) mem_malloc((rp->num_verts+num_new_verts) * sizeof(*newverts)); + + ASSERT(newverts != NULL); + + for (int i=0;inum_verts;i++) + { + newverts[i] = rp->verts[i]; + } + + mem_free(rp->verts); + + rp->verts = newverts; + + rp->num_verts += num_new_verts; + + return (rp->num_verts - num_new_verts); +} + +//Create space for additional faces in a room. +//Allocates a new faces array, copies from the old list, and frees the old list +//The new faces are at the end of the list, so none of the old faces change number +//Parameters: rp - the room +// num_new_faces - how many faces are being added to the room +//Returns: the number of the first new face +int RoomAddFaces(room *rp,int num_new_faces) +{ + int i; + + if (num_new_faces == 0) + return 0; + + face *newfaces = (face *) mem_malloc((rp->num_faces + num_new_faces) * sizeof(*newfaces)); + + ASSERT(newfaces != NULL); + + for (i=0;inum_faces;i++) + newfaces[i] = rp->faces[i]; + + mem_free(rp->faces); + + rp->faces = newfaces; + rp->num_faces += num_new_faces; + + if(rp->num_bbf_regions) + { + for(i = 0; i < rp->num_bbf_regions; i++) + { + mem_free(rp->bbf_list[i]); + } + mem_free(rp->bbf_list); + mem_free(rp->num_bbf); + mem_free(rp->bbf_list_min_xyz); + mem_free(rp->bbf_list_max_xyz); + mem_free(rp->bbf_list_sector); + + rp->num_bbf_regions = 0; + } + + return (rp->num_faces - num_new_faces); +} + +//Check if a point is inside, outside, or on an edge of a polygon +//Parameters: checkv - the point to be checked +// v1,v0 - the edge to check against. Two sequential verts in a clockwise polygon. +// normal - the surface normal of the polygon +//Returns: 1 if the point in inside the edge +// 0 if the point is on the edge +// -1 if the point is outside the edge +int CheckPointAgainstEdge(vector *checkv,vector *v0,vector *v1,vector *normal) +{ + int ii,jj; + float edge_i,edge_j,check_i,check_j; + float *vv0,*vv1,*checkvv; + float edge_mag,dot; + + //Get the vertices for projection + GetIJ(normal,&ii,&jj); + + //Get pointers to elements of our vectors + vv0 = (float *) v0; + vv1 = (float *) v1; + checkvv = (float *) checkv; + + //Get 2d vector for edge + edge_i = vv1[ii] - vv0[ii]; + edge_j = vv1[jj] - vv0[jj]; + edge_mag = sqrt(edge_i * edge_i + edge_j * edge_j); + + //Get 2d vector for check point + check_i = checkvv[ii] - vv0[ii]; + check_j = checkvv[jj] - vv0[jj]; + + //Now do the dot product to see if the check point is on the front + dot = ((-edge_j * check_i) + (edge_i * check_j)) / edge_mag; + + //Check dot value and return appropriate code + if (dot > POINT_TO_EDGE_EPSILON) + return -1; + else if (dot < -POINT_TO_EDGE_EPSILON) + return 1; + else + return 0; +} + +//Clips on edge of a polygon against another edge +//Parameters: normal - defines the plane in which these edgs lie +// v0,v1 - the edge to be clipped +// v2,v3 - is the edge clipped against +// newv - filled in with the intersection point +void ClipEdge(vector *normal,vertex *v0,vertex *v1,vector *v2,vector *v3,vertex *newv) +{ + float *vv0,*vv1,*vv2,*vv3; + float k; + int ii,jj; + + //Get the vertices for projection + GetIJ(normal,&ii,&jj); + + //Get pointers to elements of our vectors + vv0 = (float *) &v0->vec; + vv1 = (float *) &v1->vec; + vv2 = (float *) v2; + vv3 = (float *) v3; + + k = ((vv2[jj] - vv0[jj]) * (vv3[ii] - vv2[ii]) - (vv2[ii] - vv0[ii]) * (vv3[jj] - vv2[jj])) / + ((vv1[jj] - vv0[jj]) * (vv3[ii] - vv2[ii]) - (vv1[ii] - vv0[ii]) * (vv3[jj] - vv2[jj])); + + //Deal w/ precision problems + if (k < 0.0) { + ASSERT((vm_VectorDistance(&v1->vec,&v0->vec) * -k) < POINT_TO_EDGE_EPSILON); + k = 0.0; + } + if (k > 1.0) { + ASSERT((vm_VectorDistance(&v1->vec,&v0->vec) * (k-1.0)) < POINT_TO_EDGE_EPSILON); + k = 1.0; + } + + //Check for valid values of k + ASSERT((k >= 0) && (k <= 1.0)); + + newv->vec = v0->vec + (v1->vec - v0->vec) * k; + + newv->uvl.u = v0->uvl.u + (v1->uvl.u - v0->uvl.u) * k; + newv->uvl.v = v0->uvl.v + (v1->uvl.v - v0->uvl.v) * k; + newv->uvl.alpha = v0->uvl.alpha + ((v1->uvl.alpha - v0->uvl.alpha) * k); +} + +//Finds a shared edge, if one exists, between two faces in the same room +//Parameters: fp0,fp1 - pointers to the two faces +// vn0,vn1 - filled in with the vertex numbers of the edge. These vert numbers are +// relative to their own faces. The shared edge is verts on +// face 0, and on face 1 +//Returns: true if a shared edge was found, else false +bool FindSharedEdge(face *fp0,face *fp1,int *vn0,int *vn1) +{ + int i,j,a0,b0,a1,b1; + + //Go through each edge in first face + for (i=0;inum_verts;i++) { + + //Get edge verts - is edge on first face + a0 = fp0->face_verts[i]; + b0 = fp0->face_verts[(i+1)%fp0->num_verts]; + + //Check against second face + for (j=0;jnum_verts;j++) { + + //Get edge verts - is edge on second face + a1 = fp1->face_verts[j]; + b1 = fp1->face_verts[(j+1)%fp1->num_verts]; + + //@@if ((a0==a1) && (b0==b1)) + //@@ Int3(); //If you hit this, you probably have a duplicate or overlapping face + + if ((a0==b1) && (b0==a1)) { //found match! + *vn0 = i; + *vn1 = j; + return 1; + } + } + } + + //Didn't find an edge, so return error + return 0; +} + +//Finds a shared edge, if one exists, between two faces in different rooms +//Parameters: rp0,rp1 - pointers to the two rooms +// face0,face1 - the face numbers in rp0 & rp1, respectively +// vn0,vn1 - filled in with the vertex numbers of the edge. These vert numbers are +// relative to their own faces. The shared edge is verts on +// face 0, and on face 1 +//Returns: true if a shared edge was found, else false +bool FindSharedEdgeAcrossRooms(room *rp0,int face0,room *rp1,int face1,int *vn0,int *vn1) +{ + int i,j; + vector *va0,*vb0,*va1,*vb1; + face *fp0,*fp1; + + //Get pointers to the two faces + fp0 = &rp0->faces[face0]; + fp1 = &rp1->faces[face1]; + + //Go through each edge in first face + for (i=0;inum_verts;i++) { + + //Get edge verts - is edge on first face + va0 = &rp0->verts[fp0->face_verts[i]]; + vb0 = &rp0->verts[fp0->face_verts[(i+1)%fp0->num_verts]]; + + //Check against second face + for (j=0;jnum_verts;j++) { + + //Get edge verts - is edge on second face + va1 = &rp1->verts[fp1->face_verts[j]]; + vb1 = &rp1->verts[fp1->face_verts[(j+1)%fp1->num_verts]]; + + if (PointsAreSame(va0,va1) && PointsAreSame(vb0,vb1)) //this shouldn't happen + Int3(); + + if (PointsAreSame(va0,vb1) && PointsAreSame(vb0,va1)) { //found match! + *vn0 = i; + *vn1 = j; + return 1; + } + } + } + + //Didn't find an edge, so return error + return 0; +} + +//Delete a vertex from a room. Assumes the vertex is unused. +//Parameters: rp - pointer to room +// vertnum - the vertex to delete +void DeleteRoomVert(room *rp,int vertnum) +{ + int f,v; + face *fp; + vector *newverts; + + //Remap vertices in faces + for (f=0,fp=rp->faces;fnum_faces;f++,fp++) + for (v=0;vnum_verts;v++) + if (fp->face_verts[v] == vertnum) + Int3(); //THIS IS VERY BAD! DELETING A VERTEX STILL IN USE! + else if (fp->face_verts[v] > vertnum) + fp->face_verts[v]--; + + //malloc new list + newverts = (vector *) mem_malloc(sizeof(*newverts) * (rp->num_verts - 1)); ASSERT(newverts != NULL); + + //Copy verts to new list + for (v=0;vverts[v]; + } + + for (;vnum_verts-1;v++) + { + newverts[v] = rp->verts[v+1]; + } + + //Delete old list + mem_free(rp->verts); + + //Use new list + rp->verts = newverts; + + //Update count + rp->num_verts--; + +} + + +//Check the vertices in a room & remove unused ones +//Parameters: rp - the room to check +//Returns: the number of vertices removed +int DeleteUnusedRoomVerts(room *rp) +{ + bool vert_used[MAX_VERTS_PER_ROOM]; + int f,v; + face *fp; + int n_deleted=0;; + + //Init all the flags to unused + for (v=0;vnum_verts;v++) + vert_used[v] = 0; + + //Go through all the faces & flag the used verts + for (f=0,fp=rp->faces;fnum_faces;f++,fp++) + for (v=0;vnum_verts;v++) + vert_used[fp->face_verts[v]] = 1; + + //Now delete the unused verts + for (v=rp->num_verts-1;v>=0;v--) + if (! vert_used[v]) { + DeleteRoomVert(rp,v); + n_deleted++; + } + + //Done + return n_deleted; +} + +//Delete a face from a room +//Parameters: rp - the room the face is in +// facenum - the face to be deleted +void DeleteRoomFace(room *rp,int facenum,bool delete_unused_verts) +{ + int p,f,i,t; + face *newfaces; + + //Check for trigger on this face + if (rp->faces[facenum].flags & FF_HAS_TRIGGER) + DeleteTrigger(ROOMNUM(rp),facenum); + + //Adjust face numbers in portals + for (p=0;pnum_portals;p++) { + portal *pp = &rp->portals[p]; + ASSERT(pp->portal_face != facenum); + if (pp->portal_face > facenum) + pp->portal_face--; + } + + //Adjust face numbers in triggers + for (t=0;troomnum == ROOMNUM(rp)) { + ASSERT(tp->facenum != facenum); + if (tp->facenum > facenum) + tp->facenum--; + } + } + + //Allocate new face list + newfaces = (face *) mem_malloc(sizeof(*newfaces) * (rp->num_faces-1)); + ASSERT(newfaces != NULL); + + //Copy faces over + for (f=0;ffaces[f]; + for (f++;fnum_faces;f++) + newfaces[f-1] = rp->faces[f]; + +#ifdef NEWEDITOR + // Decrement texture usage + if ( ROOMNUM(rp) < MAX_ROOMS ) + { + LevelTexDecrementTexture(rp->faces[facenum].tmap); + //@@RoomTexDecrementTexture(rp->faces[facenum].tmap,m_Textures_in_use,false); + } + else + { + // TODO: for room tab, replace second line with first + ned_MarkTextureInUse(rp->faces[facenum].tmap,false); + //@@RoomTexDecrementTexture(rp->faces[facenum].tmap,m_Textures_in_use); + } +#endif + + //Free deleted face memeory + FreeRoomFace(&rp->faces[facenum]); + + //Free old face list + mem_free(rp->faces); + + //Use new face list + rp->faces = newfaces; + rp->num_faces--; + + // Adjust the current and marked faces if necessary +#ifdef NEWEDITOR + if (theApp.m_pLevelWnd != NULL) +#endif + if (rp == Curroomp) + { + if (Curface == rp->num_faces) + Curface = rp->num_faces-1; + else if (Curface > rp->num_faces) + Int3(); // this shouldn't be + if (Markedface == rp->num_faces) + Markedface = rp->num_faces-1; + else if (Markedface > rp->num_faces) + Int3(); // this shouldn't be + } + + if(rp->num_bbf_regions) + { + for(i = 0; i < rp->num_bbf_regions; i++) + { + mem_free(rp->bbf_list[i]); + } + mem_free(rp->bbf_list); + mem_free(rp->num_bbf); + mem_free(rp->bbf_list_min_xyz); + mem_free(rp->bbf_list_max_xyz); + mem_free(rp->bbf_list_sector); + + rp->num_bbf_regions = 0; + } + + //Get rid of any now-unused verts + if (delete_unused_verts) + DeleteUnusedRoomVerts(rp); +} + +//Deletes a portal from a room. Does not delete this portal this connects to +//Parameters: rp - the room the portal is in +// portalnum - the portal to be deleted +void DeleteRoomPortal(room *rp,int portalnum) +{ + portal *pp = &rp->portals[portalnum]; + face *fp = &rp->faces[pp->portal_face]; + portal *newportals; + + //Clear the portal field of the portal's face + ASSERT(fp->portal_num == portalnum); + fp->portal_num = -1; + + //Renumber all portals that come after this one + for (int p=portalnum+1;pnum_portals;p++) { + portal *tp = &rp->portals[p]; + + //Renumber the face in this portal + ASSERT(rp->faces[tp->portal_face].portal_num == p); + rp->faces[tp->portal_face].portal_num--; + + //Renumber the link back to this portal + if (tp->croom != -1) + Rooms[tp->croom].portals[tp->cportal].cportal--; + } + + //Alloc new portal list + if (rp->num_portals == 1) + newportals = NULL; + else { + newportals = (portal *) mem_malloc(sizeof(*newportals) * (rp->num_portals-1)); + ASSERT(newportals != NULL); + } + + //Copy portals over + for (p=0;pportals[p]; + for (p++;pnum_portals;p++) + newportals[p-1] = rp->portals[p]; + + //Free old portal list + mem_free(rp->portals); + + //Use the new list + rp->portals = newportals; + rp->num_portals--; +} + +#if 0 +//Remove holes in the room list +void CompressRooms(void) +{ + int hole,t,high_room; + + t = Highest_room_index; + high_room=Highest_room_index; + + + for (hole=0; hole < t; hole++) + if (! Rooms[hole].used) { + + // found an unused t which is a hole if a used t follows (not necessarily immediately) it. + while (! Rooms[t].used) + t--; + + if (t > hole) { + room *rp; + int objnum; + + // Ok, hole is the index of a hole, t is the index of a t which follows it. + // Copy t into hole, update pointers to it, update Curroomp, Markedroomp if necessary. + Rooms[hole] = Rooms[t]; + Rooms[t].used = 0; + + if (Curroomp == &Rooms[t]) + Curroomp = &Rooms[hole]; + + if (Markedroomp == &Rooms[t]) + Markedroomp = &Rooms[hole]; + + //Fix connections + rp = &Rooms[hole]; + for (int p=0;pnum_portals;p++) { + portal *pp = &rp->portals[p]; + + if (pp->croom == -1) { //a terrain connection + for (int l=0;lcroom].portals[pp->cportal].croom == t); + Rooms[pp->croom].portals[pp->cportal].croom = hole; + } + } + + //Update object room pointers + for (objnum = rp->objects; objnum != -1; objnum = Objects[objnum].next) { + ASSERT(Objects[objnum].roomnum == t); + Objects[objnum].roomnum = hole; + } + + //Fix triggers + for (p=0;p hole) + } // end if + + while (! Rooms[Highest_room_index].used) + Highest_room_index--; +} + +// Compress mine by getting rid of holes the the room array +void CompressMine() +{ + //if (Do_duplicate_vertex_check) { + // med_combine_duplicate_vertices(Vertex_active); + // Do_duplicate_vertex_check = 0; + //} + + CompressRooms(); +} +#endif + +//Copies the contents of one face to another. +//Parameters: dfp - pointer to the destination face. This face should be uninitialized. +// sfp - pointer to the source face +void CopyPortal(face *dfp,face *sfp) +{ + InitRoomFace(dfp,sfp->num_verts); + + dfp->flags = sfp->flags; + dfp->portal_num = sfp->portal_num; + dfp->normal = sfp->normal; + dfp->tmap = sfp->tmap; + + for (int i=0;inum_verts;i++) { + dfp->face_verts[i] = sfp->face_verts[i]; + dfp->face_uvls[i] = sfp->face_uvls[i]; + } +} + +//Copies the data from one room into another +//Note: Portals are not copied, and the new room will have zero portals +//Parameters: destp - the destination room of the copy +// srcp - the source room for the copy +void CopyRoom(room *destp,room *srcp) +{ + //Initialize the new room + InitRoom(destp,srcp->num_verts,srcp->num_faces,0); + + //Copy over the faces + for (int i=0;inum_faces;i++) + { + CopyFace(&destp->faces[i],&srcp->faces[i]); +#ifdef NEWEDITOR + LevelTexIncrementTexture(srcp->faces[i].tmap); +#endif + } + + //Copy over the verts + for (i=0;inum_verts;i++) + destp->verts[i] = srcp->verts[i]; + + //Copy doorway info + if (srcp->doorway_data) { + destp->doorway_data = (doorway *) mem_malloc(sizeof(*destp->doorway_data)); + *destp->doorway_data = *srcp->doorway_data; + } + + //Copy over the rest of the data + destp->flags = srcp->flags; + + // Copy over room lighting + Room_multiplier[destp-Rooms]=Room_multiplier[srcp-Rooms]; + Room_ambience_r[destp-Rooms]=Room_ambience_r[srcp-Rooms]; + Room_ambience_g[destp-Rooms]=Room_ambience_g[srcp-Rooms]; + Room_ambience_b[destp-Rooms]=Room_ambience_b[srcp-Rooms]; +} + +//Adds a new portal for this room. Returns the portal number. +//Initializes the flags +int AddPortal(room *rp) +{ + portal *newlist; + int i; + + newlist = (portal *) mem_malloc(sizeof(*newlist) * (rp->num_portals+1)); + + //Copy from old list to new list, and free old list + if (rp->num_portals) { + + for (i=0;inum_portals;i++) + newlist[i] = rp->portals[i]; + + mem_free(rp->portals); + } + + //Point at new list + rp->portals = newlist; + + //Init flags + rp->portals[rp->num_portals].flags = 0; + rp->portals[rp->num_portals].bnode_index = -1; + + return rp->num_portals++; +} + +//Links two rooms, creating portals in each room +//Parameters: roomlist - pointer to the array of rooms +// room0,face0 - the room & face numbers of the first room +// room1,face1 - the room & face numbers of the second room +void LinkRooms(room *roomlist,int room0,int face0,int room1,int face1) +{ + room *rp0,*rp1; + int pn0,pn1; + int nv0,nv1; + + //Set some vars + rp0 = &roomlist[room0]; + rp1 = &roomlist[room1]; + nv0 = rp0->faces[face0].num_verts; + nv1 = rp1->faces[face1].num_verts; + + //Make sure no portals already + ASSERT(rp0->faces[face0].portal_num == -1); + ASSERT(rp1->faces[face1].portal_num == -1); + + //Check for match + if (nv0 != nv1) + Int3(); //You must get Matt if you hit this! + + //Create portals + pn0 = AddPortal(rp0); + pn1 = AddPortal(rp1); + + //Link portals + rp0->portals[pn0].croom = room1; + rp0->portals[pn0].cportal = pn1; + rp1->portals[pn1].croom = room0; + rp1->portals[pn1].cportal = pn0; + + //Add faces to portals + rp0->portals[pn0].portal_face = face0; + rp1->portals[pn1].portal_face = face1; + + //Mark faces as being part of portals + rp0->faces[face0].portal_num = pn0; + rp1->faces[face1].portal_num = pn1; +} + +//Finds the min and max x,y,z values of the vertices in a room +//Parameters: min,max - filled in with the minimum and maximum x,y, & z values, respectively +// rp = the room +void ComputeRoomMinMax(vector *min,vector *max,room *rp) +{ + min->x = min->y = min->z = FLT_MAX; + max->x = max->y = max->z = -FLT_MAX; + + for (int i=0;inum_verts;i++) { + if (rp->verts[i].x > max->x) + max->x = rp->verts[i].x; + if (rp->verts[i].y > max->y) + max->y = rp->verts[i].y; + if (rp->verts[i].z > max->z) + max->z = rp->verts[i].z; + + if (rp->verts[i].x < min->x) + min->x = rp->verts[i].x; + if (rp->verts[i].y < min->y) + min->y = rp->verts[i].y; + if (rp->verts[i].z < min->z) + min->z = rp->verts[i].z; + } +} + +//Builds a list of all the vertices in a room that are part of a portal +//Parameters: rp - the room to check +// list - filled in with the list of vert numbers. List should be MAX_VERTS_PER_ROOM big +//Returns: the number of verts in the list +int BuildListOfPortalVerts (room *rp,int *list) +{ + int i,t,j; + int count=0; + + for (i=0;inum_portals;i++) + { + face *fp = &rp->faces[rp->portals[i].portal_face]; + + for (t=0;tnum_verts;t++) + { + int v = fp->face_verts[t]; + + for (j=0;j= BUF_LEN) + OutrageMessageBox("There has been a text buffer overflow in CheckError()."); + +} + +//Checks the normals in a room +//Returns the number of bad normals +int CheckNormals(room *rp) +{ + int errors = 0; + + for (int f=0;fnum_faces;f++) + if (! ComputeFaceNormal(rp,f)) { + CheckError("Room %3d face %3d has a bad or low-precision normal\n",ROOMNUM(rp),f); + errors++; + } + + return errors; +} + +//Checks for concave faces +//Returns the number of concave faces +int CheckConcaveFaces(room *rp) +{ + int f; + face *fp; + int errors = 0; + + //Go through all the faces + for (f=0,fp=rp->faces;fnum_faces;f++,fp++) { + + int vert = CheckFaceConcavity(fp->num_verts,fp->face_verts,&fp->normal,rp->verts); + if (vert != -1) { + CheckError("Room %3d face %3d is concave at vertex %d\n",ROOMNUM(rp),f,vert); + errors++; + } + } + + return errors; +} + +int CheckDegenerateFaces(room *rp) +{ + int errors = 0; + int f,v; + face *fp; + + //Go through all the faces + for (f=0,fp=rp->faces;fnum_faces;f++,fp++) { + for (v=0;vnum_verts;v++) + if (fp->face_verts[v] == fp->face_verts[(v+2)%fp->num_verts]) { + CheckError("Room %3d face %3d is degenerate\n",ROOMNUM(rp),f); + errors++; + break; + } + } + + return errors; +} + +//Make sure the two faces of a portal match +//Returns true if the portal is ok +bool CheckPortal(room *rp0,int p0) +{ + int i,j,p1; + room *rp1; + portal *pp0,*pp1; + face *fp0,*fp1; + + //Get info + pp0 = &rp0->portals[p0]; + rp1 = &Rooms[pp0->croom]; + p1 = pp0->cportal; + pp1 = &rp1->portals[p1]; + fp0 = &rp0->faces[pp0->portal_face]; + fp1 = &rp1->faces[pp1->portal_face]; + + //Make sure faces have the same number of verts + if (fp0->num_verts != fp1->num_verts) { + CheckError("Room %d portal %d has a different number of vertices (%d) than room %d portal %d (%d)\n",ROOMNUM(rp0),p0,fp0->num_verts,ROOMNUM(rp1),p1,fp1->num_verts); + return 0; + } + + //Find one point in common + for (i=0;inum_verts;i++) { + for (j=0;jnum_verts;j++) + if (PointsAreSame(&rp0->verts[fp0->face_verts[i]],&rp1->verts[fp1->face_verts[j]])) + break; + if (j < fp1->num_verts) + break; + } + if (i >= fp0->num_verts) { + CheckError("Cannot find a single matching point between room %d portal %d and room %d portal %d\n",ROOMNUM(rp0),p0,ROOMNUM(rp1),p1); + return 0; + } + + vector *v0,*v1,*prev0,*prev1; + int n; + + //Trace through verts in faces, making sure they match + prev0 = &rp0->verts[fp0->face_verts[i]]; + prev1 = &rp1->verts[fp1->face_verts[j]]; + for (n=1;nnum_verts;n++) { + + v0 = &rp0->verts[fp0->face_verts[(i+n) % fp0->num_verts]]; + v1 = &rp1->verts[fp1->face_verts[(j-n+fp1->num_verts) % fp1->num_verts]]; + + if (! PointsAreSame(v0,v1)) { + CheckError("Vertex %d in room %d portal %d does not match vertex %d in room %d portal %d\n",(i+n) % fp0->num_verts,ROOMNUM(rp0),p0,(j-n+fp1->num_verts) % fp1->num_verts,ROOMNUM(rp1),p1); + return 0; + } + } + + return 1; +} + +extern void DumpTextToClipboard(char *text); + +//Checks for bad portal connections +//Returns the number of bad portals +int CheckPortals(room *rp) +{ + portal *pp; + int p; + int r=ROOMNUM(rp); + int errors=0; + + for (p=0,pp=rp->portals;pnum_portals;pp++,p++) { + + //Make sure the connecting portal points back to this portal + if ((Rooms[pp->croom].portals[pp->cportal].croom != r) || (Rooms[pp->croom].portals[pp->cportal].cportal != p)) { + CheckError("Room %d, portal %d points at room %d portal %d, but the latter points at room %d portal %d\n",r,p,pp->croom,pp->cportal,Rooms[pp->croom].portals[pp->cportal].croom,Rooms[pp->croom].portals[pp->cportal].cportal); + errors++; + } + + //Check to make sure the face in this portal points back to it + if (rp->faces[pp->portal_face].portal_num != p) { + CheckError("Room %d portal %d contains face %d, but that face points at portal %d\n",r,p,pp->portal_face,rp->faces[pp->portal_face].portal_num); + errors++; + } + } + + return errors; +} + +//Checks if the given face is a duplicate of another face +//Returns the face number of which this is a duplicate, or -1 if not a duplicate +int CheckForDuplicateFace(room *rp,int facenum) +{ + face *fp0 = &rp->faces[facenum]; + int r = ROOMNUM(rp); + + for (int j=0;jfaces[j]; + + if (fp0->num_verts == fp1->num_verts) + for (int v=0;vnum_verts;v++) //look for a shared vert + if (fp1->face_verts[v] == fp0->face_verts[0]) { + for (int t=0;tnum_verts;t++) + if (fp0->face_verts[t] != fp1->face_verts[(v+t) % fp1->num_verts]) + break; + if (t == fp0->num_verts) { + return j; + } + break; + } + } + + //Didn't find a duplicate + return -1; +} + +//Removes all the duplicate faces in a room +void RemoveDuplicateFaces(room *rp) +{ + int r = ROOMNUM(rp); + int removed = 0; + + for (int i=0;inum_faces;i++) { + int dup = CheckForDuplicateFace(rp,i); + + if (dup != -1) { + DeleteRoomFace(rp,i); + mprintf((0,"Removed face %d (duplicate of face %d) from room %d\n",i,dup,r)); + removed++; + i--; + } + } + + if (removed) { + OutrageMessageBox("%d duplicate faces have been removed from room %d.",removed,r); + World_changed = 1; + } + else + OutrageMessageBox("There are no duplicate faces in room %d.",r); +} + + +//Checks for duplicate faces +//Returns the number of duplicate faces +int CheckDuplicateFaces(room *rp) +{ + int r = ROOMNUM(rp); + int errors = 0; + + for (int i=0;inum_faces;i++) { + int dup = CheckForDuplicateFace(rp,i); + + if (dup != -1) { + CheckError("Room %d: face %d is the same as face %d\n",r,i,dup); + errors++; + } + } + + return errors; +} + +//Checks for non-planar faces +//Returns the number of non-planar faces +int CheckNonPlanarFaces(room *rp) +{ + int r = ROOMNUM(rp); + int errors = 0; + + for (int f=0;fnum_faces;f++) + if (! FaceIsPlanar(rp,f)) { + if (rp->faces[f].portal_num != -1) + CheckError("Room %d: face %d is not planar. FACE IS PORTAL!\n",r,f); + else + CheckError("Room %d: face %d is not planar\n",r,f); + errors++; + } + + return errors; +} + +//Checks for duplicate points +//Returns the number of duplicate points +int CheckDuplicatePoints(room *rp) +{ + int r = ROOMNUM(rp); + int errors = 0; + + for (int i=0;inum_verts;i++) + for (int j=0;jverts[i],&rp->verts[j])) { + float d = vm_VectorDistance(&rp->verts[i],&rp->verts[j]); + CheckError("Room %d: vert %3d is the same as vert %3d (d=%.2f)\n",r,i,j,d); + errors++; + } + + return errors; +} + +//Find any unused points in a room +int CheckUnusedPoints(room *rp) +{ + int r = ROOMNUM(rp); + int errors = 0; + bool vert_used[MAX_VERTS_PER_ROOM]; + int f,v; + face *fp; + + //Init all the flags to unused + for (v=0;vnum_verts;v++) + vert_used[v] = 0; + + //Go through all the faces & flag the used verts + for (f=0,fp=rp->faces;fnum_faces;f++,fp++) + for (v=0;vnum_verts;v++) + vert_used[fp->face_verts[v]] = 1; + + //Now delete the unused verts + for (v=0;vnum_verts;v++) + if (! vert_used[v]) { + CheckError("Room %d: point %d is unused\n",r,v); + errors++; + } + + //Done + return errors; +} + +//Checks for duplicate points in faces +//Returns the number of duplicate face points +int CheckDuplicateFacePoints(room *rp) +{ + int r = ROOMNUM(rp); + int f,v,errors = 0; + face *fp; + + for (f=0,fp=rp->faces;fnum_faces;f++,fp++) + for (v=0;vnum_verts;v++) + if (fp->face_verts[v] == fp->face_verts[(v+1)%fp->num_verts]) { + CheckError("Room %d, face %d: vert #%d (%d) is the same as #%d\n",r,f,(v+1)%fp->num_verts,fp->face_verts[v],v); + errors++; + } + + return errors; +} + +//Returns true if faces match exactly, else false +int CheckPortalFaces(room *rp0,int facenum0,room *rp1,int facenum1) +{ + face *fp0 = &rp0->faces[facenum0]; + face *fp1 = &rp1->faces[facenum1]; + vector *v0,*v1,*prev_v0,*prev_v1; + int n,i,j,prev_vn0,prev_vn1; + int points_added=0; + + //First, find one point in common + for (i=0;inum_verts;i++) { + for (j=0;jnum_verts;j++) + if (PointsAreSame(&rp0->verts[fp0->face_verts[i]],&rp1->verts[fp1->face_verts[j]])) + break; + if (j < fp1->num_verts) + break; + } + if (i >= fp0->num_verts) + return 0; + + prev_vn0 = fp0->face_verts[i]; + prev_vn1 = fp1->face_verts[j]; + prev_v0 = &rp0->verts[prev_vn0]; + prev_v1 = &rp1->verts[prev_vn1]; + + if (fp0->num_verts != fp1->num_verts) { + CheckError("Room %d: portal face %d does not match %d:%d\n",ROOMNUM(rp0),facenum0,ROOMNUM(rp1),facenum1); + return 0; + } + + //Trace through faces, adding points where needed + for (n=1;nnum_verts;n++) { + int vn0,vn1; + + vn0 = fp0->face_verts[(i+n) % fp0->num_verts]; + vn1 = fp1->face_verts[(j-n+fp1->num_verts) % fp1->num_verts]; + + v0 = &rp0->verts[vn0]; + v1 = &rp1->verts[vn1]; + + if (! PointsAreSame(v0,v1)) { //Points are at least very close. + CheckError("Room %d: portal face %d does not match %d:%d\n",ROOMNUM(rp0),facenum0,ROOMNUM(rp1),facenum1); + return 0; + } + + prev_vn0 = vn0; + prev_vn1 = vn1; + + prev_v0 = v0; + prev_v1 = v1; + } + + return 1; //no errors found, so faces ok +} + +int CheckRoomPortalFaces(room *rp) +{ + int errors = 0; + + for (int p=0;pnum_portals;p++) { + portal *pp = &rp->portals[p]; + if (! CheckPortalFaces(rp,pp->portal_face,&Rooms[pp->croom],Rooms[pp->croom].portals[pp->cportal].portal_face)) + errors++; + } + + return errors; +} + +//Find t-joints in this room +int FindTJoints(room *rp) +{ + int f,f2,v,v2; + face *fp,*fp2; + int tjoints=0; + int points_added=0; + + //Now search for and fix t-joints + for (f=0,fp=rp->faces;fnum_faces;f++,fp++) { + for (v=0;vnum_verts;v++) { + int vv0 = fp->face_verts[v], vv1 = fp->face_verts[(v+1)%fp->num_verts]; + for (f2=0,fp2=rp->faces;f2num_faces;f2++,fp2++) { + if (f2 != f) { + for (v2=0;v2num_verts;v2++) { + int tt0 = fp2->face_verts[v2], tt1 = fp2->face_verts[(v2+1)%fp2->num_verts]; + + if ((vv0 == tt1) && (vv1 == tt0)) + break; //found one, so stop + } + if (v2 < fp2->num_verts) + break; + } + } + if (f2 == rp->num_faces) { //didn't find a match + + //Look for vert on this edge + for (f2=0,fp2=rp->faces;f2num_faces;f2++,fp2++) { + if (f2 != f) { + for (v2=0;v2num_verts;v2++) { + int tt0 = fp2->face_verts[v2], tt1 = fp2->face_verts[(v2+1)%fp2->num_verts]; + + if (vv0 == tt1) { //one point maches; check if next is on the edge + if (CheckPointToPlane(&rp->verts[tt0],&rp->verts[vv0],&fp->normal) == 0) { + if (CheckPointAgainstEdge(&rp->verts[tt0],&rp->verts[vv0],&rp->verts[vv1],&fp->normal) == 0) { + //make sure the new point is actually between the two edge points + float edge_len = vm_VectorDistance(&rp->verts[vv1],&rp->verts[vv0]); + float d0 = vm_VectorDistance(&rp->verts[tt0],&rp->verts[vv0]); + float d1 = vm_VectorDistance(&rp->verts[tt0],&rp->verts[vv1]); + if ((d0 < edge_len) && (d1 < edge_len)) { + CheckError("Room %d: face %d edge %d has a T-joint\n",ROOMNUM(rp),f,v); + tjoints++; + goto next_face; + } + } + } + } + } + } + } + } + } +next_face:; + } + + return tjoints; +} + +// Counts the number of unique textures in a level, plus gives names of textures used +void CountUniqueTextures () +{ + ushort *texture_tracking=(ushort *)mem_malloc (MAX_TEXTURES*2); + ASSERT (texture_tracking); + memset (texture_tracking,0,MAX_TEXTURES*2); + + for (int i=0;i<=Highest_room_index;i++) + { + room *rp=&Rooms[i]; + if (rp->used==0) + continue; + + for (int t=0;tnum_faces;t++) + { + face *fp=&rp->faces[t]; + + if (fp->portal_num!=-1) + { + if (!(rp->portals[fp->portal_num].flags & PF_RENDER_FACES)) + continue; + } + + if (fp->tmap!=-1 && !(GameTextures[fp->tmap].flags & (TF_PROCEDURAL|TF_TEXTURE_64|TF_TEXTURE_32))) + { + texture_tracking[fp->tmap]++; + } + } + } + + // Now count totals + int total=0,total_with_lights=0; + for (i=0;i60) + CheckError ("ERROR: YOU HAVE MORE THAT 60 128x128 TEXTURES...YOU *MUST* FIX THIS!\n"); + + for (i=0;itype == OBJ_SOUNDSOURCE) { + ASSERT(objp->control_type == CT_SOUNDSOURCE); + total++; + if (objp->name) + named++; + if (objp->ctype.soundsource_info.sound_index == -1) { + CheckError("Soundsource object %d (\"%s\") has no sound specified.\n",objnum,objp->name?objp->name:""); + quiet++; + if (! objp->name) + quiet_unnamed++; + } + } + } + + CheckError("This level has %d soundsource objects; %d have names, %d don't have sounds, and %d have no sounds & no name.\n",total,named,quiet,quiet_unnamed); + + return quiet; +} + + +int BOAGetMineChecksum (); + +//Get rid of large whole parts of face UV coordinates +void NormalizeFaceUVs() +{ + int r; + room *rp; + + for (r=0,rp=Rooms;r <= Highest_room_index;r++,rp++) { + if (rp->used) { + int f; + face *fp; + + for (f=0,fp=rp->faces;fnum_faces;f++,fp++) { + float base_u = floor(fp->face_uvls[0].u); + float base_v = floor(fp->face_uvls[0].v); + + for (int v=0;vnum_verts;v++) { + fp->face_uvls[v].u -= base_u; + fp->face_uvls[v].v -= base_v; + } + } + } + } +} + + +//Test the mine for validity +void VerifyMine() +{ + int r; + room *rp; + int errors=0,bad_normals=0,concave_faces=0,degenerate_faces=0,bad_portals=0,duplicate_faces=0,duplicate_points=0,duplicate_face_points=0, + unused_points=0,nonplanar_faces=0,mismatched_portals=0,tjoints=0,bad_shells=0,quiet_soundsource_objects=0; + + error_buf_offset = 0; + + //Normalize all the UV coordinates in the level + NormalizeFaceUVs(); + + //Check normals, portals, & duplicate faces + for (r=0,rp=Rooms;r<=Highest_room_index;r++,rp++) + if (rp->used) { + + bad_normals += CheckNormals(rp); + errors += bad_normals; + + concave_faces += CheckConcaveFaces(rp); + errors += concave_faces; + + degenerate_faces += CheckDegenerateFaces(rp); + errors += degenerate_faces; + + bad_portals += CheckPortals(rp); + errors += bad_portals; + + duplicate_faces += CheckDuplicateFaces(rp); + errors += duplicate_faces; + + nonplanar_faces += CheckNonPlanarFaces(rp); + errors += nonplanar_faces; + + duplicate_points += CheckDuplicatePoints(rp); + errors += duplicate_points; + + duplicate_face_points += CheckDuplicateFacePoints(rp); + errors += duplicate_face_points; + + unused_points += CheckUnusedPoints(rp); + errors += unused_points; + + mismatched_portals += CheckRoomPortalFaces(rp); + errors += mismatched_portals; + + tjoints += FindTJoints(rp); + errors += tjoints; + + if ((rp->num_portals > 0) && !(rp->flags & RF_EXTERNAL)) { + int shell_errors = ComputeRoomShell(rp); + if (shell_errors) { + bad_shells++; + errors++; + } + } + } + + quiet_soundsource_objects = CheckSoundsourceObjects(); + errors += quiet_soundsource_objects; + + CountUniqueTextures (); + + bool terrain_occluded=false; + bool boa_ran=false; + bool terrain_volume=false; + + if (Terrain_occlusion_checksum==(Terrain_checksum+1)) + terrain_occluded=true; + else + errors=1; + + if (BOAGetMineChecksum()==BOA_vis_checksum) + boa_ran=true; + else + errors=true; + + // Check to see if dynamic terrain lighting is calculated + for (int i=0;iflags = 0; + + //@@if (sfp->flags & FF_FORCEFIELD) + //@@ dfp->flags |= FF_FORCEFIELD; + + if (sfp->flags & FF_GOALFACE) + dfp->flags |= FF_GOALFACE; +} + +//Inserts a vertex into a face +//Parameters: rp - the room for this face +// facenum - the face to which to add the vertex +// new_v - the number of the vertex to add +// after_v - the new vert is added *after* this vert (index into face verts) +void AddVertToFace(room *rp,int facenum,int new_v,int after_v) +{ + face *fp = &rp->faces[facenum]; + int old_verts[MAX_VERTS_PER_FACE]; + roomUVL old_uvls[MAX_VERTS_PER_FACE]; + int t; + + //Make copy of old verts + for (t=0;tnum_verts;t++) { + old_verts[t] = fp->face_verts[t]; + old_uvls[t] = fp->face_uvls[t]; + } + + //Allocate for new verts + ReInitRoomFace(fp,fp->num_verts+1); + + //Copy old verts + for (t=0;t<=after_v;t++) { + fp->face_verts[t] = old_verts[t]; + fp->face_uvls[t] = old_uvls[t]; + } + + //Insert new vert + fp->face_verts[t++] = new_v; + + //Copy rest of new verts + for (;tnum_verts;t++) { + fp->face_verts[t] = old_verts[t-1]; + fp->face_uvls[t] = old_uvls[t-1]; + } + + //Compute the uv values for the new vert + vector *v0 = &rp->verts[fp->face_verts[after_v]], + *v1 = &rp->verts[fp->face_verts[(after_v+2)%fp->num_verts]], + *vn = &rp->verts[fp->face_verts[after_v+1]]; + roomUVL *uv0 = &fp->face_uvls[after_v], + *uv1 = &fp->face_uvls[(after_v+2)%fp->num_verts]; + + float k = vm_VectorDistance(vn,v0) / vm_VectorDistance(v1,v0); + + fp->face_uvls[after_v+1].u = uv0->u + k * (uv1->u - uv0->u); + fp->face_uvls[after_v+1].v = uv0->v + k * (uv1->v - uv0->v); + fp->face_uvls[after_v+1].u2 = uv0->u2 + k * (uv1->u2 - uv0->u2); + fp->face_uvls[after_v+1].v2 = uv0->v2 + k * (uv1->v2 - uv0->v2); + fp->face_uvls[after_v+1].alpha = uv0->alpha + k * (uv1->alpha - uv0->alpha); +} + +//Removes the duplicate points in a room +//Returns the number removed +int RemoveDuplicatePoints(room *rp) +{ + face *fp; + int f,v; + int n_fixed = 0; + + for (int i=0;inum_verts;i++) + for (int j=0;jverts[i],&rp->verts[j])) { + + //Replace the higher-numbered point with the lower-numbered in all the faces in this room + for (f=0,fp=rp->faces;fnum_faces;f++,fp++) + for (v=0;vnum_verts;v++) + if (fp->face_verts[v] == i) + fp->face_verts[v] = j; + + //Delete the now-unused vert + DeleteRoomVert(rp,i); + + n_fixed++; + + i--; //back up, since the point we're checking is now gone + break; //don't keep checking for duplicates + } + + return n_fixed; +} + +//Remove duplicate points in faces +//Returns the number of duplicate face points removed +int RemoveDuplicateFacePoints(room *rp) +{ + int r = ROOMNUM(rp); + int f,v,n_fixed=0; + face *fp; + + for (f=0,fp=rp->faces;fnum_faces;f++,fp++) + for (v=0;vnum_verts;v++) + if (fp->face_verts[v] == fp->face_verts[(v+1)%fp->num_verts]) { + int new_verts[MAX_VERTS_PER_FACE]; + roomUVL new_uvls[MAX_VERTS_PER_FACE]; + + for (int t=0;tface_verts[t]; + new_uvls[t] = fp->face_uvls[t]; + } + for (;tnum_verts-1;t++) { + new_verts[t] = fp->face_verts[t+1]; + new_uvls[t] = fp->face_uvls[t+1]; + } + + ReInitRoomFace(fp,fp->num_verts-1); + + for (t=0;tnum_verts;t++) { + fp->face_verts[t] = new_verts[t]; + fp->face_uvls[t] = new_uvls[t]; + } + + n_fixed++; + f--; fp--; //recheck this face + break; + } + + return n_fixed; +} + +//Removes all the duplicate points in a level +void RemoveAllDuplicateAndUnusedPoints() +{ + int r; + room *rp; + int n_unused=0,n_duplicate=0,n_duplicate_face=0; + + for (r=0,rp=Rooms;r<=Highest_room_index;r++,rp++) + if (rp->used) { + n_unused += DeleteUnusedRoomVerts(rp); + n_duplicate += RemoveDuplicatePoints(rp); + n_duplicate_face += RemoveDuplicateFacePoints(rp); + } + + OutrageMessageBox( + " %d Unused points deleted\n" + " %d Duplicate points deleted\n" + " %d Duplicate face points deleted\n", + n_unused,n_duplicate,n_duplicate_face + ); + + if (n_unused || n_duplicate || n_duplicate_face) + World_changed = 1; +} + +//Returns the number fixed +void FixDegenerateFaces() +{ + int fixed=0,deleted=0; + int r,f,v; + face *fp; + room *rp; + + for (r=0,rp=Rooms;r<=Highest_room_index;r++,rp++) { + if (rp->used) { + for (f=0,fp=rp->faces;fnum_faces;f++,fp++) { + bool face_fixed = 0; +recheck_face:; + if (fp->num_verts < 3) { + DeleteRoomFace(rp,f); + deleted++; + face_fixed = 0; //deleted overrides fixed + f--; fp = &rp->faces[f]; + } + else { + for (v=0;vnum_verts;v++) { + if (fp->face_verts[v] == fp->face_verts[(v+2)%fp->num_verts]) { + short tverts[MAX_VERTS_PER_FACE]; + roomUVL tuvls[MAX_VERTS_PER_FACE]; + + for (int i=0;inum_verts-2;i++) { + tverts[i] = fp->face_verts[(v+2+i)%fp->num_verts]; + tuvls[i] = fp->face_uvls[(v+2+i)%fp->num_verts]; + } + for (i=0;inum_verts-2;i++) { + fp->face_verts[i] = tverts[i]; + fp->face_uvls[i] = tuvls[i]; + } + fp->num_verts -= 2; + face_fixed = 1; + goto recheck_face; + } + } + } + if (face_fixed) + fixed++; + } + } + } + + OutrageMessageBox("%d Degenerate faces fixed\n%d Degenerate faces deleted",fixed,deleted); + + if (fixed || deleted) + World_changed = 1; +} + + +//Finda a face that connects to the specified face +//Starts looking at startface +//Returns the attached facenum, or -1 if found none +int FindConnectedFace(room *rp,int facenum,int edgenum,int startface) +{ + face *fp0 = &rp->faces[facenum],*fp1; + int a0,b0,a1,b1; + int f; + + //Get edge verts - is edge on first face + a0 = fp0->face_verts[edgenum]; + b0 = fp0->face_verts[(edgenum+1)%fp0->num_verts]; + + for (f=startface,fp1=&rp->faces[startface];fnum_faces;f++,fp1++) { + + if (f == facenum) + continue; + + for (int e=0;enum_verts;e++) { + + //Get edge verts - is edge on second face + a1 = fp1->face_verts[e]; + b1 = fp1->face_verts[(e+1)%fp1->num_verts]; + + //@@if ((a0==a1) && (b0==b1)) + //@@ Int3(); //If you hit this, you probably have a duplicate or overlapping face + + if ((a0==b1) && (b0==a1)) { //found match! + return f; + } + } + } + + return -1; //no match +} + +//Shell flags +#define SHELL_NONE 0 +#define SHELL_UNCHECKED 1 +#define SHELL_CLOSED 2 +#define SHELL_ERROR 3 + +//Finds the shell for the specified room. If the shell is found with no errors, sets +//the non-shell flag for those faces not in the shell. If there are errors finding the +//shell, all faces have the non-shell flag cleared. +//Assumes all portals are part of the shell and starts checking from those faces +//Returns the number of shell errors (unconnected edges) in the room. +//Writes errors to the error buffer +int ComputeRoomShell(room *rp) +{ + ubyte shell_flags[MAX_FACES_PER_ROOM]; + bool done=0; + int errors=0; + int f; + + for (f=0;fnum_faces;f++) + shell_flags[f] = SHELL_NONE; + + //Start with the portal faces + ASSERT(rp->num_portals > 0); + for (int p=0;pnum_portals;p++) + shell_flags[rp->portals[p].portal_face] = SHELL_UNCHECKED; + + //Check all the unchecked faces + while (! done) { + + for (f=0;fnum_faces;f++) { + + if (shell_flags[f] == SHELL_UNCHECKED) { + face *fp = &rp->faces[f]; + + for (int e=0;enum_verts;e++) { + + int t = FindConnectedFace(rp,f,e,0); + + if (t != -1) { + int t2; + + //See if any additional faces + t2 = FindConnectedFace(rp,f,e,t+1); + if (t2 != -1) { + //mprintf((0,"Room %d face %d: Found second connection for edge %d (face %d)\n",ROOMNUM(rp),f,e,t)); + //CheckError("Room %d face %d: Found second connection for edge %d (face %d)\n",ROOMNUM(rp),f,e,t); + } + else { //No double-edge, so add connected face + + if (shell_flags[t] == SHELL_NONE) + shell_flags[t] = SHELL_UNCHECKED; + } + } + else { + //mprintf((0,"Room %d face %d: No connection for edge %d\n",ROOMNUM(rp),f,e)); + CheckError("Room %d face %d: No connection for edge %d\n",ROOMNUM(rp),f,e); + shell_flags[f] = SHELL_ERROR; + errors++; + } + } + + if (shell_flags[f] == SHELL_UNCHECKED) + shell_flags[f] = SHELL_CLOSED; + + break; + } + } + + done = (f == rp->num_faces); + } + + //Clear flags + for (f=0;fnum_faces;f++) { + ASSERT(shell_flags[f] != SHELL_UNCHECKED); + rp->faces[f].flags &= ~FF_NOT_SHELL; + } + + + //If no errors, set flags for room + if (errors == 0) { + for (f=0;fnum_faces;f++) { + if (shell_flags[f] == SHELL_NONE) + rp->faces[f].flags |= FF_NOT_SHELL; + } + } + + return errors; +} + +//Finds shells for all rooms. +//Returns the number of rooms with bad shells +int ComputeAllRoomShells() +{ + int r,bad_shells=0; + room *rp; + + error_buf_offset = 0; + + mprintf((0,"Computing room shells...")); + + for (r=0,rp=Rooms;r<=Highest_room_index;r++,rp++) { + if (rp->used && (rp->num_portals > 0) && !(rp->flags & RF_EXTERNAL)) { + int errors = ComputeRoomShell(rp); + if (errors) + bad_shells++; + } + } + + mprintf((0,"Done\n")); + + mprintf((0,"Error buf size = %d\n",strlen(error_buf))); + + DumpTextToClipboard(error_buf); + + return bad_shells; +} + +#include "objinfo.h" +#include "mission.h" + +void ListObjectsInLevel(int *object_counts) +{ + int i; + object *objp; + + for (i=0;itype)) + object_counts[objp->id]++; + } + + CheckError("\n Robots:\n"); + for (i=0;i on +// face 0, and on face 1 +//Returns: true if a shared edge was found, else false +bool FindSharedEdge(face *fp0,face *fp1,int *vn0,int *vn1); + +//Finds a shared edge, if one exists, between two faces in different rooms +//Parameters: rp0,rp1 - pointers to the two rooms +// face0,face1 - the face numbers in rp0 & rp1, respectively +// vn0,vn1 - filled in with the vertex numbers of the edge. These vert numbers are +// relative to their own faces. The shared edge is verts on +// face 0, and on face 1 +//Returns: true if a shared edge was found, else false +bool FindSharedEdgeAcrossRooms(room *rp0,int face0,room *rp1,int face1,int *vn0,int *vn1); + +//If two surface normals have a dot product greater than or equal to this value, they are the same +#define NORMALS_SAME_VALUE .999f + +//Determines if two normals are the same (or very very close) +//Parameters: n0,n1 - the two normals +//Returns: true if they are more-or-less the same, else false +inline bool NormalsAreSame(vector *n0,vector *n1) +{ + float d = *n0 * *n1; + + return (d > NORMALS_SAME_VALUE); +} + +//Delete a face from a room +//Parameters: rp - the room the face is in +// facenum - the face to be deleted +void DeleteRoomFace(room *rp,int facenum,bool delete_unused_verts = true); + +//Deletes a portal from a room. Does not delete this portal this connects to +//Parameters: rp - the room the portal is in +// portalnum - the portal to be deleted +void DeleteRoomPortal(room *rp,int portalnum); + +//Remove holes in the room list +void CompressRooms(void); + +// Compress mine by getting rid of holes the the room array +void CompressMine(void); + +//Copies the data from one room into another +//Note: Portals are not copied, and the new room will have zero portals +//The destination room is assumed to be uninitialized +//Parameters: destp - the destination room of the copy +// srcp - the source room for the copy +void CopyRoom(room *destp,room *srcp); + +//Links two rooms, creating portals in each room +//Parameters: roomlist - pointer to the array of rooms +// room0,face0 - the room & face numbers of the first room +// room1,face1 - the room & face numbers of the second room +void LinkRooms(room *roomlist,int room0,int face0,int room1,int face1); + +//Back when we had multi-face portals, LinkRoomsSimple() created a pair of 1-face portals +#define LinkRoomsSimple LinkRooms + +//Finds the min and max x,y,z values of the vertices in a room +//Parameters: min,max - filled in with the minimum and maximum x,y, & z values, respectively +// rp = the room +void ComputeRoomMinMax(vector *min,vector *max,room *rp); + +//Builds a list of all the vertices in a room that are part of a portal +//Parameters: rp - the room to check +// list - filled in with the list of vert numbers. List should be MAX_VERTS_PER_ROOM big +//Returns: the number of verts in the list +int BuildListOfPortalVerts (room *rp,int *list); + +//Copy the flags from one face to another derrived from the first (by clipping or splitting) +//Only those flags which are safe to copy are copied +//Parameters: dfp - pointer to the destination face +// sfp - pointer to the source face +void CopyFaceFlags(face *dfp,face *sfp); + +//Test the mine for validity +void VerifyMine(); + +//Test the given room for validity +void VerifyRoom(room *rp); + +//Inserts a vertex into a face +//Parameters: rp - the room for this face +// facenum - the face to which to add the vertex +// new_v - the number of the vertex to add +// after_v - the new vert is added *after* this vert (index into face verts) +void AddVertToFace(room *rp,int facenum,int new_v,int after_v); + +//Removes all the duplicate points in a level +void RemoveAllDuplicateAndUnusedPoints(); + +//Checks to see if a face is planar. +//See if all the points are within a certain distance of an average point +//Returns 1 if face is planar, 0 if not +bool FaceIsPlanar(int nv,short *face_verts,vector *normal,vector *verts); + +//Checks to see if a face is planar. +//See if all the points are within a certain distance of an average point +//Returns 1 if face is planar, 0 if not +inline bool FaceIsPlanar(room *rp,int facenum) +{ + face *fp = &rp->faces[facenum]; + + return FaceIsPlanar(fp->num_verts,fp->face_verts,&fp->normal,rp->verts); +} + +//Finds the shell for the specified room. If the shell is found with no errors, sets +//the non-shell flag for those faces not in the shell. If there are errors finding the +//shell, all faces have the non-shell flag cleared. +//Returns the number of shell errors (unconnected edges) in the room. +//Writes errors to the error buffer +int ComputeRoomShell(room *rp); + +//Finds shells for all rooms. +//Returns the number of rooms with bad shells +int ComputeAllRoomShells(); + +//Log an error in the room check process +void CheckError(char *str,...); + +//Checks the normals in a room +//Returns the number of bad normals +int CheckNormals(room *rp); + +//Checks for concave faces +//Returns the number of concave faces +int CheckConcaveFaces(room *rp); + +int CheckDegenerateFaces(room *rp); + +//Checks for bad portal connections +//Returns the number of bad portals +int CheckPortals(room *rp); + +//Checks for duplicate faces +//Returns the number of duplicate faces +int CheckDuplicateFaces(room *rp); + +//Checks for non-planar faces +//Returns the number of non-planar faces +int CheckNonPlanarFaces(room *rp); + +//Checks for duplicate points +//Returns the number of duplicate points +int CheckDuplicatePoints(room *rp); + +//Find any unused points in a room +int CheckUnusedPoints(room *rp); + +//Checks for duplicate points in faces +//Returns the number of duplicate face points +int CheckDuplicateFacePoints(room *rp); + +int CheckRoomPortalFaces(room *rp); + +//Find t-joints in this room +int FindTJoints(room *rp); + +// Counts the number of unique textures in a level, plus gives names of textures used +void CountUniqueTextures (); + +//Removes all the duplicate faces in a room +void RemoveDuplicateFaces(room *rp); + +#endif //ifndef _EROOMS_H diff --git a/editor/FilePageAddDlg.cpp b/editor/FilePageAddDlg.cpp new file mode 100644 index 00000000..36dff1fd --- /dev/null +++ b/editor/FilePageAddDlg.cpp @@ -0,0 +1,499 @@ +// FilePageAddDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "editor.h" +#include "FilePageAddDlg.h" +#include "ddio.h" +#include "mem.h" +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFilePageAddDlg dialog + + +CFilePageAddDlg::CFilePageAddDlg(CWnd* pParent /*=NULL*/) + : CDialog(CFilePageAddDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CFilePageAddDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_NumberOfSelectedFiles = 0; + m_SelectedFiles = NULL; + m_SelectedDestDir = NULL; + initial_path = ""; +} + +CFilePageAddDlg::~CFilePageAddDlg(void) +{ + if(m_SelectedFiles) + { + for(int i=0;i